Measure time elapsed in Python?
我想要的是开始计算代码中某个地方的时间,然后获取经过的时间,以度量执行很少的函数所花费的时间。我想我用的时间模块是错误的,但是文档对我来说就是混乱。
1 2 3 4 5 6 | import timeit start = timeit.timeit() print"hello" end = timeit.timeit() print end - start |
如果只想测量两点之间经过的墙壁时钟时间,可以使用
1 2 3 4 5 6 | import time start = time.time() print("hello") end = time.time() print(end - start) |
这将以秒为单位给出执行时间。
3.3之后的另一个选择可能是使用
On Unix, return the current processor time as a floating point number
expressed in seconds. The precision, and in fact the very definition
of the meaning of"processor time", depends on that of the C function
of the same name.On Windows, this function returns wall-clock seconds elapsed since the
first call to this function, as a floating point number, based on the
Win32 functionQueryPerformanceCounter() . The resolution is typically
better than one microsecond.Deprecated since version 3.3: The behaviour of this function depends
on the platform: useperf_counter() orprocess_time() instead,
depending on your requirements, to have a well defined behaviour.
用
1 2 3 4 5 6 | 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+上,默认的_计时器是所有平台上的time.perf_counter()。参见python-time.clock()与time.time()-精度?
参见:
- 优化代码
- 如何优化速度
Python 3只:
由于从python 3.3开始不推荐使用time.clock(),因此您将希望使用
1 2 3 4 5 | import time t = time.process_time() #do some stuff elapsed_time = time.process_time() - t |
新功能
给定一个你想计时的函数,
测试:PY:
1 2 3 | def foo(): # print"hello" return"hello" |
使用
1 2 | % python -mtimeit -s'import test' 'test.foo()' 1000000 loops, best of 3: 0.254 usec per loop |
不要试图使用
ps.不要将打印语句放入您希望计时的函数中;否则,所测量的时间将取决于终端的速度。
使用上下文管理器可以自动记住进入
核心库没有这个(但可能应该有)。一旦就位,您可以执行以下操作:
1 2 3 4 5 6 | 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代码足以完成这一技巧:
1 2 3 4 5 6 7 8 9 10 | 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 |
以及一些可运行的演示代码:
1 2 3 4 5 6 7 8 | import time with elapsed_timer() as elapsed: time.sleep(1) print(elapsed()) time.sleep(2) print(elapsed()) time.sleep(3) |
注意,通过这个函数的设计,
我更喜欢这个。
1 2 3 4 5 6 7 8 9 | 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)) |
注意,这里没有任何格式,我只是在打印输出中写入了
使用
关于
- 使用Timeit模块
- timeit–计时执行少量python代码的时间
如果您想更深入地了解分析:
- http://wiki.python.org/moin/pythonspeed/performancetips分析代码
- 如何分析python脚本?
更新:去年我经常使用http://pythonhosted.org/line_profiler/并发现它非常有用,建议使用它而不是pythons profile模块。
下面是一个返回"hh:mm:ss"字符串的小计时器类:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 |
用途:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | # 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 |
python cprofile和pstats模块为测量某些函数所用的时间提供了极大的支持,而无需在现有函数周围添加任何代码。
例如,如果您有一个python脚本timefunctions.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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() |
要运行探查器并为文件生成统计信息,您只需运行:
1 | python -m cProfile -o timeStats.profile timeFunctions.py |
这样做的目的是使用cprofile模块对timefunctions.py中的所有函数进行概要分析,并在timestats.profile文件中收集统计信息。请注意,我们不必向现有模块(timefunctions.py)添加任何代码,这可以在任何模块中完成。
一旦您有了stats文件,就可以按如下方式运行pstats模块:
1 | python -m pstats timeStats.profile |
这将运行交互式统计浏览器,为您提供许多不错的功能。对于您的特定用例,您可以检查函数的统计信息。在我们的示例中,检查两个函数的统计信息显示了以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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) |
这个虚拟的例子做的不多,但会给你一个可以做什么的概念。这种方法最好的一点是,我不必编辑任何现有的代码来获取这些数字,而且明显有助于分析。
这是另一个用于计时代码的上下文管理器-
用途:
1 2 3 4 5 6 | from benchmark import benchmark with benchmark("Test 1+1"): 1+1 => Test 1+1 : 1.41e-06 seconds |
或者,如果您需要时间值
1 2 3 4 5 6 | with benchmark("Test 1+1") as b: 1+1 print(b.time) => Test 1+1 : 7.05e-07 seconds 7.05233786763e-07 |
基准:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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-benchments.html
使用探查器模块。它给出了一个非常详细的概要。
1 2 | import profile profile.run('main()') |
它输出如下内容:
1 2 3 4 5 6 7 8 9 10 11 | 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) |
我发现它很有信息量。
(仅适用于IPython)您可以使用%timeit测量平均处理时间:
1 2 | def foo(): print"hello" |
然后:
1 | %timeit foo() |
结果是:
1 | 10000 loops, best of 3: 27 μs per loop |
关于Python 3:
1 2 3 4 | from time import sleep, perf_counter as pc t0 = pc() sleep(1) print(pc()-t0) |
优雅而短小。
这是一种后来的反应,但也许对某个人来说是有目的的。这是一种非常干净的方法。
1 2 3 4 5 6 7 8 9 | 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。但是,它与任何其他功能一起工作。干杯!
以下是我在阅读了许多好的答案以及其他几篇文章之后的发现。
首先,您总是希望使用
现在的问题是,时间并不是那么简单,因为它需要设置,当你有大量的进口产品时,事情就会变得难看。理想情况下,您只需要一个装饰器或使用
定时实用模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | # 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 |
如何计时功能
现在,您只需在函数前面放置一个装饰器,就可以对其计时:
1 2 3 4 5 6 7 | import utils @utils.MeasureTime def MyBigFunc(): #do something time consuming for i in range(10000): print(i) |
如何计时代码块
如果您想对代码的时间部分进行计时,那么只需将其放在
1 2 3 4 5 6 7 8 9 10 | 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 |
优势
有几个半支持的版本浮动,所以我想指出一些亮点:
使用timeit的另一种方法:
1 2 3 4 5 6 7 | from timeit import timeit def func(): return 1 + 1 time = timeit(func, number=1) print(time) |
我们也可以把时间转换成人类可读的时间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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') |
我为这个做了一个库,如果你想测量一个函数,你可以这样做
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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
你可以用timeit。
下面是一个关于如何使用python repl测试naive_func的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | >>> 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 |
如果函数没有任何参数,则不需要包装函数。
测量时间(秒):
1 2 3 4 5 6 | from timeit import default_timer as timer from datetime import timedelta start = timer() end = timer() print(timedelta(seconds=end-start)) |
我能想到的唯一方法就是使用
1 2 3 4 5 6 | 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) |
希望能有所帮助。
最好简单地使用timeit:(它为同一命令运行多个运行,并给出结果)。
示例如下:
1 | %timeit import pandas as pd |
除了IPython中的
1 2 3 4 5 6 7 | In [1]: %%timeit ...: complex_func() ...: 2 + 2 == 5 ...: ...: 1 s ± 1.93 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) |
同样,它也可以用在Jupyter笔记本上,只需把魔术师