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

import timeit
start = timeit.timeit()
print("hello")
end = timeit.timeit()
print(end - start)

当前回答

如果您想方便地对函数计时,可以使用一个简单的修饰符:

import time

def timing_decorator(func):
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        original_return_val = func(*args, **kwargs)
        end = time.perf_counter()
        print("time elapsed in ", func.__name__, ": ", end - start, sep='')
        return original_return_val

    return wrapper

您可以在您希望计时的函数上使用它,如下所示:

@timing_decorator
def function_to_time():
    time.sleep(1)

function_to_time()

无论何时调用function_to_time,它都会打印所用的时间和正在计时的函数的名称。

其他回答

我参加聚会已经很晚了,但这种方法以前没有涉及过。当我们想要手动对某段代码进行基准测试时,我们可能需要首先找出哪些类方法占用了执行时间,这有时并不明显。我构建了以下元类来解决这个问题:

from __future__ import annotations

from functools import wraps
from time import time
from typing import Any, Callable, TypeVar, cast

F = TypeVar('F', bound=Callable[..., Any])


def timed_method(func: F, prefix: str | None = None) -> F:
    prefix = (prefix + ' ') if prefix else ''

    @wraps(func)
    def inner(*args, **kwargs):  # type: ignore
        start = time()
        try:
            ret = func(*args, **kwargs)
        except BaseException:
            print(f'[ERROR] {prefix}{func.__qualname__}: {time() - start}')
            raise
        
        print(f'{prefix}{func.__qualname__}: {time() - start}')
        return ret

    return cast(F, inner)


class TimedClass(type):
    def __new__(
        cls: type[TimedClass],
        name: str,
        bases: tuple[type[type], ...],
        attrs: dict[str, Any],
        **kwargs: Any,
    ) -> TimedClass:
        for name, attr in attrs.items():
            if isinstance(attr, (classmethod, staticmethod)):
                attrs[name] = type(attr)(timed_method(attr.__func__))
            elif isinstance(attr, property):
                attrs[name] = property(
                    timed_method(attr.fget, 'get') if attr.fget is not None else None,
                    timed_method(attr.fset, 'set') if attr.fset is not None else None,
                    timed_method(attr.fdel, 'del') if attr.fdel is not None else None,
                )
            elif callable(attr):
                attrs[name] = timed_method(attr)

        return super().__new__(cls, name, bases, attrs)

它允许如下使用:

class MyClass(metaclass=TimedClass):
    def foo(self): 
        print('foo')
    
    @classmethod
    def bar(cls): 
        print('bar')
    
    @staticmethod
    def baz(): 
        print('baz')
    
    @property
    def prop(self): 
        print('prop')
    
    @prop.setter
    def prop(self, v): 
        print('fset')
    
    @prop.deleter
    def prop(self): 
        print('fdel')


c = MyClass()

c.foo()
c.bar()
c.baz()
c.prop
c.prop = 2
del c.prop

MyClass.bar()
MyClass.baz()

它打印:

foo
MyClass.foo: 1.621246337890625e-05
bar
MyClass.bar: 4.5299530029296875e-06
baz
MyClass.baz: 4.291534423828125e-06
prop
get MyClass.prop: 3.814697265625e-06
fset
set MyClass.prop: 3.5762786865234375e-06
fdel
del MyClass.prop: 3.5762786865234375e-06
bar
MyClass.bar: 3.814697265625e-06
baz
MyClass.baz: 4.0531158447265625e-06

它可以与其他答案相结合,以更精确的方式代替time.time。

我喜欢简单(python 3):

from timeit import timeit

timeit(lambda: print("hello"))

单个执行的输出为微秒:

2.430883963010274

说明:timeit默认执行匿名函数100万次,结果以秒为单位。因此,1次执行的结果相同,但平均以微秒为单位。


对于速度较慢的操作,添加较少的迭代次数,否则您可能会一直等待:

import time

timeit(lambda: time.sleep(1.5), number=1)

总迭代次数的输出始终以秒为单位:

1.5015795179999714

以下是一个答案,使用:

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

给定要计时的函数,

测试.py:

def foo(): 
    # print "hello"   
    return "hello"

使用timeit的最简单方法是从命令行调用它:

% python -mtimeit -s'import test' 'test.foo()'
1000000 loops, best of 3: 0.254 usec per loop

不要尝试使用time.time或time.clock(天真地)来比较函数的速度。他们会给出误导性的结果。

PS.不要将打印语句放在您希望计时的函数中;否则测量的时间将取决于终端的速度。

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)