首页 文章

测量Python中经过的时间?

提问于
浏览 1083
736

我想要的是在我的代码中的某个地方开始计算时间,然后获得通过的时间,以测量执行少量功能所花费的时间 . 我认为我使用的是timeit模块错误,但文档对我来说只是让人困惑 .

import timeit

start = timeit.timeit()
print "hello"
end = timeit.timeit()
print end - start

22 回答

  • 934

    这是一种超级后来的回应,但也许它可以为某人服务 . 我认为这是一种方法超级干净 .

    import time
    
    def timed(fun, *args):
        s = time.time()
        r = fun(*args)
        print('{} execution took {} seconds.'.format(fun.__name__, time.time()-s))
        return(r)
    
    timed(print, "Hello")
    

    请记住,“print”是Python 3中的一个函数,而不是Python 2.7 . 但是,它适用于任何其他功能 . 干杯!

  • 365

    python cProfile和pstats模块为测量某些函数所用的时间提供了极大的支持,而无需在现有函数周围添加任何代码 .

    例如,如果你有一个python脚本timeFunctions.py:

    import time
    
    def hello():
        print "Hello :)"
        time.sleep(0.1)
    
    def thankyou():
        print "Thank you!"
        time.sleep(0.05)
    
    for idx in range(10):
        hello()
    
    for idx in range(100):
        thankyou()
    

    要运行探查器并为文件生成统计信息,您只需运行:

    python -m cProfile -o timeStats.profile timeFunctions.py
    

    这样做是使用cProfile模块分析timeFunctions.py中的所有函数并收集timeStats.profile文件中的统计信息 . 请注意,我们不必向现有模块添加任何代码(timeFunctions.py),这可以通过任何模块完成 .

    获得stats文件后,可以按如下方式运行pstats模块:

    python -m pstats timeStats.profile
    

    这将运行交互式统计浏览器,为您提供许多不错的功能 . 对于您的特定用例,您只需检查您的功能的统计数据 . 在我们的示例中,检查两个函数的统计信息显示以下内容:

    Welcome to the profile statistics browser.
    timeStats.profile% stats hello
    <timestamp>    timeStats.profile
    
             224 function calls in 6.014 seconds
    
       Random listing order was used
       List reduced from 6 to 1 due to restriction <'hello'>
    
       ncalls  tottime  percall  cumtime  percall filename:lineno(function)
           10    0.000    0.000    1.001    0.100 timeFunctions.py:3(hello)
    
    timeStats.profile% stats thankyou
    <timestamp>    timeStats.profile
    
             224 function calls in 6.014 seconds
    
       Random listing order was used
       List reduced from 6 to 1 due to restriction <'thankyou'>
    
       ncalls  tottime  percall  cumtime  percall filename:lineno(function)
          100    0.002    0.000    5.012    0.050 timeFunctions.py:7(thankyou)
    

    虚拟示例没有做太多,但让您了解可以做什么 . 关于这种方法最好的部分是我不必编辑任何现有代码来获取这些数字,显然有助于分析 .

  • 94

    使用分析器模块 . 它给出了非常详细的资料 .

    import profile
    profile.run('main()')
    

    它输出如下:

    5 function calls in 0.047 seconds
    
       Ordered by: standard name
    
       ncalls  tottime  percall  cumtime  percall filename:lineno(function)
            1    0.000    0.000    0.000    0.000 :0(exec)
            1    0.047    0.047    0.047    0.047 :0(setprofile)
            1    0.000    0.000    0.000    0.000 <string>:1(<module>)
            0    0.000             0.000          profile:0(profiler)
            1    0.000    0.000    0.047    0.047 profile:0(main())
            1    0.000    0.000    0.000    0.000 two_sum.py:2(twoSum)
    

    我发现它非常有用 .

  • 71

    使用 time.time 来度量执行可以为您提供命令的总执行时间,包括计算机上其他进程所花费的运行时间 . 这是用户注意到的时间,但如果您想要比较不同的代码片段/算法/函数/ ...则不好

    有关 timeit 的更多信息:

    如果您想更深入地了解分析:

    Update :我在去年使用了http://pythonhosted.org/line_profiler/并发现它非常有用,并建议使用它代替Pythons配置文件模块 .

  • 43

    Python 3:

    从time.clock()is deprecated as of Python 3.3开始,您将需要使用time.perf_counter()进行系统范围的计时,或使用time.process_time()进行进程范围的计时,就像您以前使用 time.clock() 一样:

    import time
    
    t = time.process_time()
    #do some stuff
    elapsed_time = time.process_time() - t
    

    新功能 process_time 将不包括睡眠期间经过的时间 .

  • 41

    我能想到的唯一方法就是使用 time.time() .

    import time
    start = time.time()
    sleep(5) #just to give it some delay to show it working
    finish = time.time()
    elapsed = finish - start
    print(elapsed)
    

    希望会有所帮助 .

  • 24

    以下是我在这里通过许多好的答案以及其他一些文章后的发现 .

    首先,您总是希望使用 timeit 而不是 time.time (在很多情况下还会使用计数器API),因为

    • timeit 选择您的操作系统和Python版本上可用的最佳计时器 .

    • timeit 禁用垃圾收集,但这不是您可能想要或不想要的东西 .

    现在的问题是timeit不是那么简单,因为它需要设置,当你有大量的导入时,事情会变得很难看 . 理想情况下,您只需要装饰器或使用 with 块并测量时间 . 不幸的是,没有内置的可用内容,因此我创建了一些小实用程序模块 .

    Timing Utility Module

    # utils.py
    from functools import wraps
    import gc
    import timeit
    
    def MeasureTime(f):
        @wraps(f)
        def _wrapper(*args, **kwargs):
            gcold = gc.isenabled()
            gc.disable()
            start_time = timeit.default_timer()
            try:
                result = f(*args, **kwargs)
            finally:
                elapsed = timeit.default_timer() - start_time
                if gcold:
                    gc.enable()
                print('Function "{}": {}s'.format(f.__name__, elapsed))
            return result
        return _wrapper
    
    class MeasureBlockTime:
        def __init__(self,name="(block)", no_print = False, disable_gc = True):
            self.name = name
            self.no_print = no_print
            self.disable_gc = disable_gc
        def __enter__(self):
            if self.disable_gc:
                self.gcold = gc.isenabled()
                gc.disable()
            self.start_time = timeit.default_timer()
        def __exit__(self,ty,val,tb):
            self.elapsed = timeit.default_timer() - self.start_time
            if self.disable_gc and self.gcold:
                gc.enable()
            if not self.no_print:
                print('Function "{}": {}s'.format(self.name, self.elapsed))
            return False #re-raise any exceptions
    

    How to Time Functions

    现在你可以通过在它前面放一个装饰器来计时任何功能:

    import utils
    
    @utils.MeasureTime
    def MyBigFunc():
        #do something time consuming
        for i in range(10000):
            print(i)
    

    How to Time Code Blocks

    如果你想要时间部分代码,那么只需将其放在 with 块中:

    import utils
    
    #somewhere in my code
    
    with utils.MeasureBlockTime("MyBlock"):
        #do something time consuming
        for i in range(10000):
            print(i)
    
    # rest of my code
    

    Advantages

    有几个半支持版本浮动,所以我想指出一些亮点:

    • 出于前面所述的原因,使用timeit而不是time.time .

    • 在计时期间禁用GC .

    • Decorator接受具有命名或未命名参数的函数 .

    • 能够在块定时中禁用打印(使用 with utils.MeasureBlockTime() as t ,然后使用 t.elapsed ) .

    • 能够保持gc启用块定时 .

  • 18

    (仅限Ipython)您可以使用%timeit来测量平均处理时间:

    def foo():
        print "hello"
    

    然后:

    %timeit foo()
    

    结果是这样的:

    10000 loops, best of 3: 27 µs per loop
    
  • 16

    最好简单地使用timeit :(它为同一个命令运行多次运行并为您提供结果) .

    示例如下:

    %timeit import pandas as pd
    
  • 15

    我更喜欢这个 . timeit doc太令人困惑了 .

    from datetime import datetime 
    
    start_time = datetime.now() 
    
    # INSERT YOUR CODE 
    
    time_elapsed = datetime.now() - start_time 
    
    print('Time elapsed (hh:mm:ss.ms) {}'.format(time_elapsed))
    

    注意,这里没有任何格式化,我只是在打印输出中写了 hh:mm:ss 所以可以解释 time_elapsed

  • 14

    这是一个微小的计时器类,返回“hh:mm:ss”字符串:

    class Timer:
      def __init__(self):
        self.start = time.time()
    
      def restart(self):
        self.start = time.time()
    
      def get_time_hhmmss(self):
        end = time.time()
        m, s = divmod(end - self.start, 60)
        h, m = divmod(m, 60)
        time_str = "%02d:%02d:%02d" % (h, m, s)
        return time_str
    

    用法:

    # Start timer
    my_timer = Timer()
    
    # ... do something
    
    # Get time string:
    time_hhmmss = my_timer.get_time_hhmmss()
    print("Time elapsed: %s" % time_hhmmss )
    
    # ... use the timer again
    my_timer.restart()
    
    # ... do something
    
    # Get time:
    time_hhmmss = my_timer.get_time_hhmmss()
    
    # ... etc
    
  • 12

    使用 timeit.default_timer 而不是 timeit.timeit . 前者提供您平台上最好的时钟和自动版本的Python:

    from timeit import default_timer as timer
    
    start = timer()
    # ...
    end = timer()
    print(end - start) # Time in seconds, e.g. 5.38091952400282
    

    timeit.default_timer根据操作系统分配给time.time()或time.clock() . 在Python 3.3上default_timer在所有平台上都是time.perf_counter() . 见Python - time.clock() vs. time.time() - accuracy?

    也可以看看:

  • 9

    你可以使用timeit .

    这是一个关于如何使用Python REPL测试带参数的naive_func的示例:

    >>> import timeit                                                                                         
    
    >>> def naive_func(x):                                                                                    
    ...     a = 0                                                                                             
    ...     for i in range(a):                                                                                
    ...         a += i                                                                                        
    ...     return a                                                                                          
    
    >>> def wrapper(func, *args, **kwargs):                                                                   
    ...     def wrapper():                                                                                    
    ...         return func(*args, **kwargs)                                                                  
    ...     return wrapper                                                                                    
    
    >>> wrapped = wrapper(naive_func, 1_000)                                                                  
    
    >>> timeit.timeit(wrapped, number=1_000_000)                                                              
    0.4458435332577161
    

    如果函数没有任何参数,则不需要包装函数 .

  • 9

    如果您只想测量两点之间经过的挂钟时间,可以使用time.time()

    import time
    
    start = time.time()
    print("hello")
    end = time.time()
    print(end - start)
    

    这给出了以秒为单位的执行时间 .

    自3.3以来的另一个选择可能是使用perf_counterprocess_time,具体取决于您的要求 . 在3.3之前,建议使用time.clock(感谢Amber) . 但是,它目前已被弃用:

    在Unix上,将当前处理器时间返回为以秒为单位的浮点数 . 精确度,实际上是“处理器时间”含义的定义,取决于同名C函数的精度 . 在Windows上,此函数返回自第一次调用此函数以来经过的挂钟秒,作为浮点数,基于Win32函数QueryPerformanceCounter() . 分辨率通常优于1微秒 . 从版本3.3开始不推荐使用:此函数的行为取决于平台:根据您的要求,使用perf_counter()或process_time()来定义明确的行为 .

  • 6

    使用timeit的另一种方法:

    from timeit import timeit
    
    def func():
        return 1 + 1
    
    time = timeit(func, number=1)
    print(time)
    
  • 6

    这是定时代码的另一个上下文管理器 -

    用法:

    from benchmark import benchmark
    
    with benchmark("Test 1+1"):
        1+1
    =>
    Test 1+1 : 1.41e-06 seconds
    

    或者,如果您需要时间 Value

    with benchmark("Test 1+1") as b:
        1+1
    print(b.time)
    =>
    Test 1+1 : 7.05e-07 seconds
    7.05233786763e-07
    

    benchmark.py

    from timeit import default_timer as timer
    
    class benchmark(object):
    
        def __init__(self, msg, fmt="%0.3g"):
            self.msg = msg
            self.fmt = fmt
    
        def __enter__(self):
            self.start = timer()
            return self
    
        def __exit__(self, *args):
            t = timer() - self.start
            print(("%s : " + self.fmt + " seconds") % (self.msg, t))
            self.time = t
    

    改编自http://dabeaz.blogspot.fr/2010/02/context-manager-for-timing-benchmarks.html

  • 5

    除了ipython中的 %timeit 之外,您还可以将 %%timeit 用于多行代码片段:

    In [1]: %%timeit
       ...: complex_func()
       ...: 2 + 2 == 5
       ...:
       ...:
    
    1 s ± 1.93 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    

    它也可以在_377698中以相同的方式使用,只需将magic %%timeit放在单元格的开头 .

  • 4

    使用上下文管理器执行此操作很有趣,该上下文管理器会在进入 with 块时自动记住开始时间,然后在块退出时冻结结束时间 . 通过一些小技巧,您甚至可以从相同的上下文管理器功能获得块内运行的经过时间的计数 .

    核心库没有这个(但可能应该) . 一旦到位,您可以执行以下操作:

    with elapsed_timer() as elapsed:
        # some lengthy code
        print( "midpoint at %.2f seconds" % elapsed() )  # time so far
        # other lengthy code
    
    print( "all done at %.2f seconds" % elapsed() )
    

    这里的contextmanager代码足以完成这个诀窍:

    from contextlib import contextmanager
    from timeit import default_timer
    
    @contextmanager
    def elapsed_timer():
        start = default_timer()
        elapser = lambda: default_timer() - start
        yield lambda: elapser()
        end = default_timer()
        elapser = lambda: end-start
    

    还有一些可运行的演示代码:

    import time
    
    with elapsed_timer() as elapsed:
        time.sleep(1)
        print(elapsed())
        time.sleep(2)
        print(elapsed())
        time.sleep(3)
    

    请注意,通过此函数的设计, elapsed() 的返回值在块退出时被冻结,并且其他调用返回相同的持续时间(在此玩具示例中约为6秒) .

  • 3

    我为此创建了一个库,如果你想测量一个函数你就可以这样做

    from pythonbenchmark import compare, measure
    import time
    
    a,b,c,d,e = 10,10,10,10,10
    something = [a,b,c,d,e]
    
    @measure
    def myFunction(something):
        time.sleep(0.4)
    
    @measure
    def myOptimizedFunction(something):
        time.sleep(0.2)
    
    myFunction(input)
    myOptimizedFunction(input)
    

    https://github.com/Karlheinzniebuhr/pythonbenchmark

  • 0

    鉴于你想要的时间功能,

    test.py:

    def foo(): 
        # print "hello"   
        return "hello"
    

    使用 timeit 的最简单方法是从命令行调用它:

    % python -mtimeit -s'import test' 'test.foo()'
    1000000 loops, best of 3: 0.254 usec per loop
    

    不要试图使用 time.timetime.clock (天真)来比较函数的速度 . They can give misleading results .

    PS . 不要将打印语句放在您想要的时间函数中;否则测量的时间将取决于speed of the terminal .

  • 0

    on python3:

    from time import sleep, perf_counter as pc
    t0 = pc()
    sleep(1)
    print(pc()-t0)
    

    优雅而短暂 .

  • 0

    我们还可以将时间转换为人类可读的时间 .

    import time, datetime
    
    start = time.clock()
    
    def num_multi1(max):
        result = 0
        for num in range(0, 1000):
            if (num % 3 == 0 or num % 5 == 0):
                result += num
    
        print "Sum is %d " % result
    
    num_multi1(1000)
    
    end = time.clock()
    value = end - start
    timestamp = datetime.datetime.fromtimestamp(value)
    print timestamp.strftime('%Y-%m-%d %H:%M:%S')
    

相关问题