问题:Python时间测量功能
我想创建一个python函数来测试在每个函数中花费的时间,并用时间显示其名称,我该如何打印函数名称,如果还有另一种方法,请告诉我
def measureTime(a):
start = time.clock()
a()
elapsed = time.clock()
elapsed = elapsed - start
print "Time spent in (function name) is: ", elapsed
回答 0
但是,如果您想严格地学习自己的计时方法,可以在这里开始使用装饰器。
Python 2:
def timing(f):
def wrap(*args):
time1 = time.time()
ret = f(*args)
time2 = time.time()
print '%s function took %0.3f ms' % (f.func_name, (time2-time1)*1000.0)
return ret
return wrap
用法非常简单,只需使用@timing装饰器即可:
@timing
def do_work():
#code
Python 3:
def timing(f):
def wrap(*args, **kwargs):
time1 = time.time()
ret = f(*args, **kwargs)
time2 = time.time()
print('{:s} function took {:.3f} ms'.format(f.__name__, (time2-time1)*1000.0))
return ret
return wrap
注意我正在调用f.func_name
以字符串形式获取函数名称(在Python 2中)或f.__name__
在Python 3中。
回答 1
在玩完timeit
模块之后,我不喜欢它的界面,与下面两种方法相比,它的界面并不那么优雅。
以下代码在Python 3中。
装饰器方法
这与@Mike的方法几乎相同。在这里,我添加kwargs
并functools
包装以使其更好。
def timeit(func):
@functools.wraps(func)
def newfunc(*args, **kwargs):
startTime = time.time()
func(*args, **kwargs)
elapsedTime = time.time() - startTime
print('function [{}] finished in {} ms'.format(
func.__name__, int(elapsedTime * 1000)))
return newfunc
@timeit
def foobar():
mike = Person()
mike.think(30)
上下文管理器方法
from contextlib import contextmanager
@contextmanager
def timeit_context(name):
startTime = time.time()
yield
elapsedTime = time.time() - startTime
print('[{}] finished in {} ms'.format(name, int(elapsedTime * 1000)))
例如,您可以像这样使用它:
with timeit_context('My profiling code'):
mike = Person()
mike.think()
并且该with
块内的代码将被计时。
结论
使用第一种方法,您可以轻松地注释掉装饰器以获取常规代码。但是,它只能计时一个功能。如果您有一部分代码不是使它起作用的功能,则可以选择第二种方法。
例如,现在你有
images = get_images()
bigImage = ImagePacker.pack(images, width=4096)
drawer.draw(bigImage)
现在您要为bigImage = ...
生产线计时。如果将其更改为功能,它将是:
images = get_images()
bitImage = None
@timeit
def foobar():
nonlocal bigImage
bigImage = ImagePacker.pack(images, width=4096)
drawer.draw(bigImage)
看起来不太好…如果您使用的是没有nonlocal
关键字的Python 2,该怎么办?
相反,使用第二种方法非常适合这里:
images = get_images()
with timeit_context('foobar'):
bigImage = ImagePacker.pack(images, width=4096)
drawer.draw(bigImage)
回答 2
我看不到timeit
模块有什么问题。这可能是最简单的方法。
import timeit
timeit.timeit(a, number=1)
也可以向函数发送参数。您需要做的就是使用装饰器包装功能。此处有更多说明: http //www.pythoncentral.io/time-a-python-function/
您可能对编写自己的时序语句感兴趣的唯一情况是,您只想运行一个函数并且还希望获得其返回值。
使用该timeit
模块的优势 在于,它使您可以重复执行次数。这可能是必要的,因为其他过程可能会干扰您的计时精度。因此,您应该多次运行它并查看最小值。
回答 3
Timeit有两个大缺陷:它不返回函数的返回值,并且它使用eval,这需要为导入传递额外的设置代码。这可以简单而优雅地解决这两个问题:
def timed(f):
start = time.time()
ret = f()
elapsed = time.time() - start
return ret, elapsed
timed(lambda: database.foo.execute('select count(*) from source.apachelog'))
(<sqlalchemy.engine.result.ResultProxy object at 0x7fd6c20fc690>, 4.07547402381897)
回答 4
有一个简单的计时工具。https://github.com/RalphMao/PyTimer
它可以像装饰器一样工作:
from pytimer import Timer
@Timer(average=False)
def matmul(a,b, times=100):
for i in range(times):
np.dot(a,b)
输出:
matmul:0.368434
matmul:2.839355
它也可以像带有命名空间控制的插件计时器一样工作(如果将其插入具有很多代码并且可以在其他任何地方调用的函数,则将很有帮助)。
timer = Timer()
def any_function():
timer.start()
for i in range(10):
timer.reset()
np.dot(np.ones((100,1000)), np.zeros((1000,500)))
timer.checkpoint('block1')
np.dot(np.ones((100,1000)), np.zeros((1000,500)))
np.dot(np.ones((100,1000)), np.zeros((1000,500)))
timer.checkpoint('block2')
np.dot(np.ones((100,1000)), np.zeros((1000,1000)))
for j in range(20):
np.dot(np.ones((100,1000)), np.zeros((1000,500)))
timer.summary()
for i in range(2):
any_function()
输出:
========Timing Summary of Default Timer========
block2:0.065062
block1:0.032529
========Timing Summary of Default Timer========
block2:0.065838
block1:0.032891
希望对你有帮助
回答 5
使用装饰器Python库的Decorator方法:
import decorator
@decorator
def timing(func, *args, **kwargs):
'''Function timing wrapper
Example of using:
``@timing()``
'''
fn = '%s.%s' % (func.__module__, func.__name__)
timer = Timer()
with timer:
ret = func(*args, **kwargs)
log.info(u'%s - %0.3f sec' % (fn, timer.duration_in_seconds()))
return ret
请参阅我的博客上的文章:
回答 6
我的做法:
from time import time
def printTime(start):
end = time()
duration = end - start
if duration < 60:
return "used: " + str(round(duration, 2)) + "s."
else:
mins = int(duration / 60)
secs = round(duration % 60, 2)
if mins < 60:
return "used: " + str(mins) + "m " + str(secs) + "s."
else:
hours = int(duration / 3600)
mins = mins % 60
return "used: " + str(hours) + "h " + str(mins) + "m " + str(secs) + "s."
start = time()
在执行功能/循环之前以及printTime(start)
在块之后立即设置变量。
然后你得到了答案。