我想测量执行一个函数所花费的时间。我没时间工作:
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)
当前回答
测量小代码片段的执行时间。
时间单位:以秒为单位,以浮点数表示
import timeit
t = timeit.Timer('li = list(map(lambda x:x*2,[1,2,3,4,5]))')
t.timeit()
t.repeat()
>[1.2934070999999676, 1.3335035000000062, 1.422568500000125]
repeat()方法可以方便地多次调用timeit()并返回结果列表。重复(重复=3)¶有了这个列表,我们可以计算所有时间的平均值。默认情况下,timeit()在计时期间暂时关闭垃圾收集。time.Timer()解决了这个问题。赞成的意见:timeit.Timer()使独立计时更具可比性。gc可能是被测函数性能的重要组成部分。如果是,gc(垃圾收集器)可以作为设置字符串中的第一条语句重新启用。例如:timeit.Timer('li=列表(映射(lambda x:x*2,[1,2,3,4,5])',设置='gc.enable()')
源Python文档!
其他回答
这种独特的基于类的方法提供了可打印的字符串表示、可自定义的舍入,以及以字符串或浮点形式方便地访问经过的时间。它是用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
以下是我在阅读了许多好答案以及其他几篇文章之后的发现。
首先,如果你在timeit和time.time之间进行辩论,timeit有两个优点:
timeit选择操作系统和Python版本上可用的最佳计时器。然而,timeit禁用垃圾收集,这不是您可能想要或不想要的。
现在的问题是,时间并不是那么简单,因为它需要设置,当你有大量的导入时,事情会变得很糟糕。理想情况下,您只需要一个装饰器或使用块和度量时间。不幸的是,没有内置功能可用于此,因此您有两个选项:
选项1:使用时间预算库
timebudget是一个多功能且非常简单的库,您可以在pip安装后仅在一行代码中使用它。
@timebudget # Record how long this function takes
def my_method():
# my code
选项2:使用我的小模块
我创建了一个名为timing.py的计时实用程序模块。只需将这个文件放到项目中并开始使用它。唯一的外部依赖是runstats,它同样很小。
现在,只需在函数前面放置一个装饰器,就可以对任何函数计时:
import timing
@timing.MeasureTime
def MyBigFunc():
#do something time consuming
for i in range(10000):
print(i)
timing.print_all_timings()
如果您想对代码的一部分计时,只需将其放入块中:
import timing
#somewhere in my code
with timing.MeasureBlockTime("MyBlock"):
#do something time consuming
for i in range(10000):
print(i)
# rest of my code
timing.print_all_timings()
优势:
有几个半备份版本,所以我想指出几个亮点:
出于前面描述的原因,请使用timeit中的计时器,而不是time.time。如果需要,可以在计时期间禁用GC。Decorator接受带有命名或未命名参数的函数。能够在块计时中禁用打印(与timing.MeasureBlockTime()一起使用为t,然后为t.passed)。能够为块计时启用gc。
作为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'
>>>
基于https://stackoverflow.com/a/30024601/5095636,以下为无lambda版本,如flake8根据E731对lambda使用的警告:
from contextlib import contextmanager
from timeit import default_timer
@contextmanager
def elapsed_timer():
start_time = default_timer()
class _Timer():
start = start_time
end = default_timer()
duration = end - start
yield _Timer
end_time = default_timer()
_Timer.end = end_time
_Timer.duration = end_time - start_time
测试:
from time import sleep
with elapsed_timer() as t:
print("start:", t.start)
sleep(1)
print("end:", t.end)
t.start
t.end
t.duration
这里有一个很好的文档记录和完全类型提示的装饰器,我将其用作通用工具:
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