准确的时间在Python中的function
我在Windows上编程python,并希望准确测量function运行所需的时间。 我写了一个函数“time_it”,它接受另一个函数,运行它,并返回运行所需的时间。
def time_it(f, *args): start = time.clock() f(*args) return (time.clock() - start)*1000
我把这1000次称为平均值。 (最后的1000常数是以毫秒为单位给出答案)。
这个函数似乎可行,但是我有这种唠叨的感觉,我做错了什么,而且通过这样做,我使用的时间超过了函数在运行时实际使用的时间。
有没有更标准或可接受的方式来做到这一点?
当我改变我的testing函数调用打印,以便它需要更长的时间,我的time_it函数返回平均2.5毫秒,而cProfile.run('f()')返回和平均7.0毫秒。 我想我的function会高估时间,如果有的话,这是怎么回事?
还有一点需要注意的是,我所关心的function的相对时间是相对的,而不是绝对的时间,因为硬件和其他因素会有明显的变化。
我build议您不要编写自己的分析代码,而应该查看内置的Python分析器( profile
或cProfile
,取决于您的需要): http : cProfile
使用Python标准库中的timeit
模块 。
基本用法:
from timeit import Timer # first argument is the code to be run, the second "setup" argument is only run once, # and it not included in the execution time. t = Timer("""x.index(123)""", setup="""x = range(1000)""") print t.timeit() # prints float, for example 5.8254 # ..or.. print t.timeit(1000) # repeat 1000 times instead of the default 1million
你可以像这样创build一个“timeme”装饰器
import time def timeme(method): def wrapper(*args, **kw): startTime = int(round(time.time() * 1000)) result = method(*args, **kw) endTime = int(round(time.time() * 1000)) print(endTime - startTime,'ms') return result return wrapper @timeme def func1(a,b,c = 'c',sleep = 1): time.sleep(sleep) print(a,b,c) func1('a','b','c',0) func1('a','b','c',0.5) func1('a','b','c',0.6) func1('a','b','c',1)
这个代码是非常不准确的
total= 0 for i in range(1000): start= time.clock() function() end= time.clock() total += end-start time= total/1000
这个代码不太准确
start= time.clock() for i in range(1000): function() end= time.clock() time= (end-start)/1000
如果函数的运行时间接近于时钟的精度,则非常不准确的会受到测量偏差的影响。 大部分测量的时间只是0到几个时钟之间的随机数。
根据您的系统工作负载,您从单个函数观察到的“时间”可能完全是操作系统调度和其他不可控制的开销的人为因素。
第二个版本(不太准确)的测量偏差较小。 如果你的function真的很快,你可能需要运行一万次来减less操作系统调度和其他开销。
当然,这两者都是极具误导性的。 程序的运行时间 – 整体而言 – 不是函数运行时间的总和。 您只能使用数字进行相对比较。 他们不是绝对的测量,传达了很多的意义。
如果你想要一个Python方法,即使你测量的块可能抛出,一个好方法是使用语句。 定义一些Timer
类作为
import time class Timer: def __enter__(self): self.start = time.clock() return self def __exit__(self, *args): self.end = time.clock() self.interval = self.end - self.start
那么你可能想要一个可能抛出的连接方法。 使用
import httplib with Timer() as t: conn = httplib.HTTPConnection('google.com') conn.request('GET', '/') print('Request took %.03f sec.' % t.interval)
__exit()__
方法将被调用,即使连接请求thows。 更确切地说,你最好使用try
来查看结果,以防万一抛出
try: with Timer() as t: conn = httplib.HTTPConnection('google.com') conn.request('GET', '/') finally: print('Request took %.03f sec.' % t.interval)
更多细节在这里。
这很整洁
from contextlib import contextmanager import time @contextmanager def timeblock(label): start = time.clock() try: yield finally: end = time.clock() print ('{} : {}'.format(label, end - start)) with timeblock("just a test"): print "yippee"
类似@ AlexMartelli的答案
import timeit timeit.timeit(fun, number=10000)
可以做的伎俩。