我想测量执行一个函数所花费的时间。我没时间工作:
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 time
start_time = time.monotonic()
<operations, programs>
print('seconds: ', time.monotonic() - start_time)
这里有官方文件。
其他回答
python cProfile和pstats模块为测量某些函数的时间提供了强大的支持,而无需在现有函数周围添加任何代码。
例如,如果您有python脚本timeFunctions.py:
import time
def hello():
print "Hello :)"
time.sleep(0.1)
def thankyou():
print "Thank you!"
time.sleep(0.05)
for idx in range(10):
hello()
for idx in range(100):
thankyou()
要运行探查器并生成文件的统计信息,只需运行:
python -m cProfile -o timeStats.profile timeFunctions.py
这是在使用cProfile模块来评测timeFunctions.py中的所有函数,并在timeStats.profile文件中收集统计信息。注意,我们不必向现有模块(timeFunctions.py)添加任何代码,这可以通过任何模块来完成。
一旦有了stats文件,就可以按如下方式运行pstats模块:
python -m pstats timeStats.profile
这将运行交互式统计浏览器,它为您提供了许多不错的功能。对于您的特定用例,您可以只检查函数的统计信息。在我们的示例中,检查两个函数的统计信息显示如下:
Welcome to the profile statistics browser.
timeStats.profile% stats hello
<timestamp> timeStats.profile
224 function calls in 6.014 seconds
Random listing order was used
List reduced from 6 to 1 due to restriction <'hello'>
ncalls tottime percall cumtime percall filename:lineno(function)
10 0.000 0.000 1.001 0.100 timeFunctions.py:3(hello)
timeStats.profile% stats thankyou
<timestamp> timeStats.profile
224 function calls in 6.014 seconds
Random listing order was used
List reduced from 6 to 1 due to restriction <'thankyou'>
ncalls tottime percall cumtime percall filename:lineno(function)
100 0.002 0.000 5.012 0.050 timeFunctions.py:7(thankyou)
这个假例子做不了什么,但给了你一个可以做什么的想法。这种方法最好的一点是,我不必编辑任何现有代码来获取这些数字,并且显然有助于分析。
要深入了解递归调用的每个函数,请执行以下操作:
%load_ext snakeviz
%%snakeviz
它只需要在Jupyter笔记本中使用这两行代码,就可以生成一个很好的交互图。例如:
这是代码。同样,以%开头的2行是使用snakeviz所需的唯一额外代码行:
# !pip install snakeviz
%load_ext snakeviz
import glob
import hashlib
%%snakeviz
files = glob.glob('*.txt')
def print_files_hashed(files):
for file in files:
with open(file) as f:
print(hashlib.md5(f.read().encode('utf-8')).hexdigest())
print_files_hashed(files)
在笔记本外运行snakeviz似乎也是可能的。更多信息请访问snakeviz网站。
我参加聚会已经很晚了,但这种方法以前没有涉及过。当我们想要手动对某段代码进行基准测试时,我们可能需要首先找出哪些类方法占用了执行时间,这有时并不明显。我构建了以下元类来解决这个问题:
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。
时间也可以通过%timeit魔法函数测量,如下所示:
%timeit -t -n 1 print("hello")
n 1仅用于运行功能1次。
print_elapsed_time函数如下
def print_elapsed_time(prefix=''):
e_time = time.time()
if not hasattr(print_elapsed_time, 's_time'):
print_elapsed_time.s_time = e_time
else:
print(f'{prefix} elapsed time: {e_time - print_elapsed_time.s_time:.2f} sec')
print_elapsed_time.s_time = e_time
用这种方式
print_elapsed_time()
.... heavy jobs ...
print_elapsed_time('after heavy jobs')
.... tons of jobs ...
print_elapsed_time('after tons of jobs')
结果是
after heavy jobs elapsed time: 0.39 sec
after tons of jobs elapsed time: 0.60 sec
这个函数的优点和缺点是你不需要经过开始时间