我想测量执行一个函数所花费的时间。我没时间工作:
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)
当前回答
这种独特的基于类的方法提供了可打印的字符串表示、可自定义的舍入,以及以字符串或浮点形式方便地访问经过的时间。它是用Python 3.7开发的。
import datetime
import timeit
class Timer:
"""Measure time used."""
# Ref: https://stackoverflow.com/a/57931660/
def __init__(self, round_ndigits: int = 0):
self._round_ndigits = round_ndigits
self._start_time = timeit.default_timer()
def __call__(self) -> float:
return timeit.default_timer() - self._start_time
def __str__(self) -> str:
return str(datetime.timedelta(seconds=round(self(), self._round_ndigits)))
用法:
# Setup timer
>>> timer = Timer()
# Access as a string
>>> print(f'Time elapsed is {timer}.')
Time elapsed is 0:00:03.
>>> print(f'Time elapsed is {timer}.')
Time elapsed is 0:00:04.
# Access as a float
>>> timer()
6.841332235
>>> timer()
7.970274425
其他回答
这里有一个很好的文档记录和完全类型提示的装饰器,我将其用作通用工具:
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
以下是一个答案,使用:
对代码片段进行计时的简洁上下文管理器time.perf_counter()计算时间增量。与time.time()相反,它是不可调整的(sysadmin和守护程序都不能更改其值),因此应该首选它(参见文档)python3.10+(因为键入,但可以很容易地适应以前的版本)
import time
from contextlib import contextmanager
from typing import Iterator
@contextmanager
def time_it() -> Iterator[None]:
tic: float = time.perf_counter()
try:
yield
finally:
toc: float = time.perf_counter()
print(f"Computation time = {1000*(toc - tic):.3f}ms")
如何使用它的示例:
# Example: vector dot product computation
with time_it():
A = B = range(1000000)
dot = sum(a*b for a,b in zip(A,B))
# Computation time = 95.353ms
附录
import time
# to check adjustability
assert time.get_clock_info('time').adjustable
assert time.get_clock_info('perf_counter').adjustable is False
我们还可以将时间转换为人类可读的时间。
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')
这种独特的基于类的方法提供了可打印的字符串表示、可自定义的舍入,以及以字符串或浮点形式方便地访问经过的时间。它是用Python 3.7开发的。
import datetime
import timeit
class Timer:
"""Measure time used."""
# Ref: https://stackoverflow.com/a/57931660/
def __init__(self, round_ndigits: int = 0):
self._round_ndigits = round_ndigits
self._start_time = timeit.default_timer()
def __call__(self) -> float:
return timeit.default_timer() - self._start_time
def __str__(self) -> str:
return str(datetime.timedelta(seconds=round(self(), self._round_ndigits)))
用法:
# Setup timer
>>> timer = Timer()
# Access as a string
>>> print(f'Time elapsed is {timer}.')
Time elapsed is 0:00:03.
>>> print(f'Time elapsed is {timer}.')
Time elapsed is 0:00:04.
# Access as a float
>>> timer()
6.841332235
>>> timer()
7.970274425
使用一个上下文管理器可以很有趣地做到这一点,它可以自动记住进入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() )
以下是足以完成此任务的contextmanager代码:
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
以及一些可运行的演示代码:
import time
with elapsed_timer() as elapsed:
time.sleep(1)
print(elapsed())
time.sleep(2)
print(elapsed())
time.sleep(3)
注意,通过设计此函数,elapsed()的返回值在块退出时被冻结,并且进一步的调用返回相同的持续时间(在这个玩具示例中大约为6秒)。