我想测量执行一个函数所花费的时间。我没时间工作:

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

其他回答

您可以使用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]

基于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

在python3上:

from time import sleep, perf_counter as pc
t0 = pc()
sleep(1)
print(pc()-t0)

优雅而短小。

下面是一个返回“hh:mm:ss”字符串的小型计时器类:

class Timer:
  def __init__(self):
    self.start = time.time()

  def restart(self):
    self.start = time.time()

  def get_time_hhmmss(self):
    end = time.time()
    m, s = divmod(end - self.start, 60)
    h, m = divmod(m, 60)
    time_str = "%02d:%02d:%02d" % (h, m, s)
    return time_str

用法:

# Start timer
my_timer = Timer()

# ... do something

# Get time string:
time_hhmmss = my_timer.get_time_hhmmss()
print("Time elapsed: %s" % time_hhmmss )

# ... use the timer again
my_timer.restart()

# ... do something

# Get time:
time_hhmmss = my_timer.get_time_hhmmss()

# ... etc

以下是一个答案,使用:

对代码片段进行计时的简洁上下文管理器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