我想测量执行一个函数所花费的时间。我没时间工作:
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)
当前回答
这里有一个很好的文档记录和完全类型提示的装饰器,我将其用作通用工具:
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
其他回答
作为lambda,获取经过的时间和时间戳:
import datetime
t_set = lambda: datetime.datetime.now().astimezone().replace(microsecond=0)
t_diff = lambda t: str(t_set() - t)
t_stamp = lambda t=None: str(t) if t else str(t_set())
在实践中:
>>>
>>> t_set()
datetime.datetime(2021, 3, 21, 1, 25, 17, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200), 'PDT'))
>>> t = t_set()
>>> t_diff(t)
'0:00:14'
>>> t_diff(t)
'0:00:23'
>>> t_stamp()
'2021-03-21 01:25:57-07:00'
>>> t_stamp(t)
'2021-03-21 01:25:22-07:00'
>>>
使用一个上下文管理器可以很有趣地做到这一点,它可以自动记住进入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秒)。
除了ipython中的%timeit之外,您还可以使用%%timeit进行多行代码片段:
In [1]: %%timeit
...: complex_func()
...: 2 + 2 == 5
...:
...:
1 s ± 1.93 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
同样,它也可以以同样的方式在jupyter笔记本中使用,只需将magic%%timeit放在单元格的开头。
您可以使用Benchmark Timer(免责声明:我是作者):
基准计时器使用BenchmarkTimer类来测量执行某段代码所需的时间。这比内置的timeit函数具有更大的灵活性,并且与其他代码在相同的范围内运行。安装pip安装git+https://github.com/michaelitvin/benchmark-timer.git@main#egg=基准计时器用法单次迭代示例从benchmark_timer导入BenchmarkTimer导入时间使用BenchmarkTimer(name=“MySimpleCode”)作为tm,tm.single_ieration():睡眠时间(.3)输出:正在对标MySimpleCode。。。MySimpleCode基准:n_iters=1 avg=0.300881s std=0.000000s range=[0.3000881s ~ 0.300881s]多次迭代示例从benchmark_timer导入BenchmarkTimer导入时间使用BenchmarkTimer(name=“MyTimedCode”,print_iters=True)作为tm:对于tm迭代中的timing_iteration(n=5,预热=2):定时重复:睡眠时间(.1)打印(“\n===============\n”)print(“定时列表:”,列表(tm.timenings.values()))输出:正在对标MyTimedCode。。。[MyTimedCode]iter=0耗时0.099755s(预热)[MyTimedCode]iter=1耗时0.100476秒(预热)[MyTimedCode]iter=2耗时0.100189秒[MyTimedCode]iter=3耗时0.099900s[MyTimedCode]iter=4耗时0.100888秒MyTimedCode基准:n_iters=3 avg=0.100326s std=0.000414s range=[0.099900s ~ 0.100888s]===================时间列表:[0.1001885000000001,0.09990049999999995,0.10088760000000008]
使用time.time()测量两点之间经过的墙上时钟时间:
import time
start = time.time()
print("hello")
end = time.time()
print(end - start)
这给出了以秒为单位的执行时间。
Python 3.3之后的另一个选项可能是使用perf_counter或process_time,具体取决于您的需求。在3.3之前,建议使用time.clock(感谢Amber)。但是,它目前已被弃用:
在Unix上,将当前处理器时间作为浮点数返回以秒表示。准确度,事实上就是定义“处理器时间”的含义取决于C函数的含义具有相同名称。在Windows上,此函数返回自该函数的第一次调用,作为浮点数,基于Win32函数QueryPerformanceCounter()。分辨率通常为优于一微秒。自3.3版起已弃用:此函数的行为取决于在平台上:改用perf_counter()或process_time(),根据您的要求,要有明确的行为。