我想测量执行一个函数所花费的时间。我没时间工作:
import timeit
start = timeit.timeit()
print("hello")
end = timeit.timeit()
print(end - start)
我想测量执行一个函数所花费的时间。我没时间工作:
import timeit
start = timeit.timeit()
print("hello")
end = timeit.timeit()
print(end - start)
当前回答
你可以使用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
若函数并没有任何参数,那个么就不需要包装函数。
其他回答
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)
这个假例子做不了什么,但给了你一个可以做什么的想法。这种方法最好的一点是,我不必编辑任何现有代码来获取这些数字,并且显然有助于分析。
使用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.cclock()与time.time()-精度?
另请参见:
正在优化代码如何优化速度
timeit模块适合对一小段Python代码进行计时。它至少可以三种形式使用:
1-作为命令行模块
python2 -m timeit 'for i in xrange(10): oct(i)'
2-对于短代码,将其作为参数传递。
import timeit
timeit.Timer('for i in xrange(10): oct(i)').timeit()
3-对于较长的代码,如:
import timeit
code_to_test = """
a = range(100000)
b = []
for i in a:
b.append(i*2)
"""
elapsed_time = timeit.timeit(code_to_test, number=100)/100
print(elapsed_time)
使用探查器模块。它提供了非常详细的概况。
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)
我发现它很有启发性。
这里有一个很好的文档记录和完全类型提示的装饰器,我将其用作通用工具:
from functools import wraps
from time import perf_counter
from typing import Any, Callable, Optional, TypeVar, cast
F = TypeVar("F", bound=Callable[..., Any])
def timer(prefix: Optional[str] = None, precision: int = 6) -> Callable[[F], F]:
"""Use as a decorator to time the execution of any function.
Args:
prefix: String to print before the time taken.
Default is the name of the function.
precision: How many decimals to include in the seconds value.
Examples:
>>> @timer()
... def foo(x):
... return x
>>> foo(123)
foo: 0.000...s
123
>>> @timer("Time taken: ", 2)
... def foo(x):
... return x
>>> foo(123)
Time taken: 0.00s
123
"""
def decorator(func: F) -> F:
@wraps(func)
def wrapper(*args: Any, **kwargs: Any) -> Any:
nonlocal prefix
prefix = prefix if prefix is not None else f"{func.__name__}: "
start = perf_counter()
result = func(*args, **kwargs)
end = perf_counter()
print(f"{prefix}{end - start:.{precision}f}s")
return result
return cast(F, wrapper)
return decorator
示例用法:
from timer import timer
@timer(precision=9)
def takes_long(x: int) -> bool:
return x in (i for i in range(x + 1))
result = takes_long(10**8)
print(result)
输出:耗时:4.942629056秒真的
可以通过以下方式检查doctest:
$ python3 -m doctest --verbose -o=ELLIPSIS timer.py
类型提示:
$ mypy timer.py