现在的问题是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启用块定时 .
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
使用上下文管理器执行此操作很有趣,该上下文管理器会在进入 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() )
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")
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()
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)
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')
22 回答
(仅限Ipython)您可以使用%timeit来测量平均处理时间:
然后:
结果是这样的:
这是一个微小的计时器类,返回“hh:mm:ss”字符串:
用法:
使用
time.time
来度量执行可以为您提供命令的总执行时间,包括计算机上其他进程所花费的运行时间 . 这是用户注意到的时间,但如果您想要比较不同的代码片段/算法/函数/ ...则不好有关
timeit
的更多信息:Using the timeit Module
timeit – Time the execution of small bits of Python code
如果您想更深入地了解分析:
http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Profiling_Code
How can you profile a python script?
Update :我在去年使用了http://pythonhosted.org/line_profiler/并发现它非常有用,并建议使用它代替Pythons配置文件模块 .
以下是我在这里通过许多好的答案以及其他一些文章后的发现 .
首先,您总是希望使用
timeit
而不是time.time
(在很多情况下还会使用计数器API),因为timeit
选择您的操作系统和Python版本上可用的最佳计时器 .timeit
禁用垃圾收集,但这不是您可能想要或不想要的东西 .现在的问题是timeit不是那么简单,因为它需要设置,当你有大量的导入时,事情会变得很难看 . 理想情况下,您只需要装饰器或使用
with
块并测量时间 . 不幸的是,没有内置的可用内容,因此我创建了一些小实用程序模块 .Timing Utility Module
How to Time Functions
现在你可以通过在它前面放一个装饰器来计时任何功能:
How to Time Code Blocks
如果你想要时间部分代码,那么只需将其放在
with
块中:Advantages
有几个半支持版本浮动,所以我想指出一些亮点:
出于前面所述的原因,使用timeit而不是time.time .
在计时期间禁用GC .
Decorator接受具有命名或未命名参数的函数 .
能够在块定时中禁用打印(使用
with utils.MeasureBlockTime() as t
,然后使用t.elapsed
) .能够保持gc启用块定时 .
你可以使用timeit .
这是一个关于如何使用Python REPL测试带参数的naive_func的示例:
如果函数没有任何参数,则不需要包装函数 .
使用分析器模块 . 它给出了非常详细的资料 .
它输出如下:
我发现它非常有用 .
我为此创建了一个库,如果你想测量一个函数你就可以这样做
https://github.com/Karlheinzniebuhr/pythonbenchmark
除了ipython中的
%timeit
之外,您还可以将 %%timeit 用于多行代码片段:它也可以在_377698中以相同的方式使用,只需将magic %%timeit放在单元格的开头 .
仅
Python 3:
从time.clock()is deprecated as of Python 3.3开始,您将需要使用time.perf_counter()进行系统范围的计时,或使用time.process_time()进行进程范围的计时,就像您以前使用
time.clock()
一样:新功能
process_time
将不包括睡眠期间经过的时间 .我更喜欢这个 .
timeit
doc太令人困惑了 .注意,这里没有任何格式化,我只是在打印输出中写了
hh:mm:ss
所以可以解释time_elapsed
最好简单地使用timeit :(它为同一个命令运行多次运行并为您提供结果) .
示例如下:
使用上下文管理器执行此操作很有趣,该上下文管理器会在进入
with
块时自动记住开始时间,然后在块退出时冻结结束时间 . 通过一些小技巧,您甚至可以从相同的上下文管理器功能获得块内运行的经过时间的计数 .核心库没有这个(但可能应该) . 一旦到位,您可以执行以下操作:
这里的contextmanager代码足以完成这个诀窍:
还有一些可运行的演示代码:
请注意,通过此函数的设计,
elapsed()
的返回值在块退出时被冻结,并且其他调用返回相同的持续时间(在此玩具示例中约为6秒) .鉴于你想要的时间功能,
test.py:
使用
timeit
的最简单方法是从命令行调用它:不要试图使用
time.time
或time.clock
(天真)来比较函数的速度 . They can give misleading results .PS . 不要将打印语句放在您想要的时间函数中;否则测量的时间将取决于speed of the terminal .
这是一种超级后来的回应,但也许它可以为某人服务 . 我认为这是一种方法超级干净 .
请记住,“print”是Python 3中的一个函数,而不是Python 2.7 . 但是,它适用于任何其他功能 . 干杯!
on python3:
优雅而短暂 .
使用timeit的另一种方法:
我能想到的唯一方法就是使用
time.time()
.希望会有所帮助 .
如果您只想测量两点之间经过的挂钟时间,可以使用time.time():
这给出了以秒为单位的执行时间 .
自3.3以来的另一个选择可能是使用perf_counter或process_time,具体取决于您的要求 . 在3.3之前,建议使用time.clock(感谢Amber) . 但是,它目前已被弃用:
python cProfile和pstats模块为测量某些函数所用的时间提供了极大的支持,而无需在现有函数周围添加任何代码 .
例如,如果你有一个python脚本timeFunctions.py:
要运行探查器并为文件生成统计信息,您只需运行:
这样做是使用cProfile模块分析timeFunctions.py中的所有函数并收集timeStats.profile文件中的统计信息 . 请注意,我们不必向现有模块添加任何代码(timeFunctions.py),这可以通过任何模块完成 .
获得stats文件后,可以按如下方式运行pstats模块:
这将运行交互式统计浏览器,为您提供许多不错的功能 . 对于您的特定用例,您只需检查您的功能的统计数据 . 在我们的示例中,检查两个函数的统计信息显示以下内容:
虚拟示例没有做太多,但让您了解可以做什么 . 关于这种方法最好的部分是我不必编辑任何现有代码来获取这些数字,显然有助于分析 .
我们还可以将时间转换为人类可读的时间 .
使用
timeit.default_timer
而不是timeit.timeit
. 前者提供您平台上最好的时钟和自动版本的Python:timeit.default_timer根据操作系统分配给time.time()或time.clock() . 在Python 3.3上default_timer在所有平台上都是time.perf_counter() . 见Python - time.clock() vs. time.time() - accuracy?
也可以看看:
Optimizing code
How to optimize for speed
这是定时代码的另一个上下文管理器 -
用法:
或者,如果您需要时间 Value
benchmark.py :
改编自http://dabeaz.blogspot.fr/2010/02/context-manager-for-timing-benchmarks.html