Измерить время, прошедшее в Python?
Я хочу начать отсчет времени где-нибудь в моем коде, а затем получить прошедшее время, чтобы измерить время, необходимое для выполнения нескольких функций. Я думаю, что неправильно использую модуль time it, но документы меня просто сбивают с толку.
import timeit
start = timeit.timeit()
print "hello"
end = timeit.timeit()
print end - start
44 ответа
В качестве лямбды получите прошедшее время и отметки времени:
import datetime
t_set = lambda: datetime.datetime.now().astimezone().replace(microsecond=0)
t_diff = lambda t: str(datetime.datetime.now().astimezone().replace(microsecond=0) - 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'
>>>
Этот уникальный подход на основе классов предлагает печатное строковое представление, настраиваемое округление и удобный доступ к истекшему времени в виде строки или числа с плавающей запятой. Он был разработан с помощью Python 3.7.
import datetime
import timeit
class Timer:
"""Measure time used."""
# Ref: https://stackru.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
Измеряйте время выполнения небольших фрагментов кода.
Единица времени: измеряется в секундах как поплавок.
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() и возвращать список результатов.
repeat(repeat=3)¶
С помощью этого списка мы можем взять среднее за все времена.
По умолчанию timeit() временно отключает сборку мусора на время. time.Timer() решает эту проблему.
Плюсы:
timeit.Timer () делает независимые тайминги более сопоставимыми. Gc может быть важным компонентом производительности измеряемой функции. Если это так, gc(сборщик мусора) можно повторно включить в качестве первого оператора в строке настройки. Например:
timeit.Timer('li = list(map(lambda x:x*2,[1,2,3,4,5]))',setup='gc.enable()')
Исходные документы Python!
import time
def getElapsedTime(startTime, units):
elapsedInSeconds = time.time() - startTime
if units == 'sec':
return elapsedInSeconds
if units == 'min':
return elapsedInSeconds/60
if units == 'hour':
return elapsedInSeconds/(60*60)
На основе решения contextmanager, предоставленного /questions/39541876/izmerit-vremya-proshedshee-v-python/39541885#39541885, ниже это бесплатная версия лямбда, поскольку flake8 предупреждает об использовании лямбда согласно E731:
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
Для Питона 3
Если вы используете
time
модуль, вы можете получить текущую метку времени, а затем выполнить свой код и снова получить метку времени. Теперь затраченное время будет первой временной меткой минус вторая временная метка:
import time
first_stamp = int(round(time.time() * 1000))
# YOUR CODE GOES HERE
time.sleep(5)
second_stamp = int(round(time.time() * 1000))
# Calculate the time taken in milliseconds
time_taken = second_stamp - first_stamp
# To get time in seconds:
time_taken_seconds = round(time_taken / 1000)
print(f'{time_taken_seconds} seconds or {time_taken} milliseconds')
Я довольно опаздываю на вечеринку, но этот подход раньше не освещался. Когда мы хотим вручную протестировать какой-то кусок кода, мы можем захотеть сначала выяснить, какой из методов класса съедает время выполнения, а это иногда неочевидно. Я построил следующий метакласс, чтобы решить именно эту проблему:
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 раз.
Вы можете использовать Benchmark Timer (отказ от ответственности: я автор):
Контрольный таймер
Использовать
BenchmarkTimer
класс для измерения времени, необходимого для выполнения некоторого фрагмента кода.
Это дает больше гибкости, чем встроенная функция timeit, и работает в той же области, что и остальная часть вашего кода.Монтаж
pip install git+https://github.com/michaelitvin/benchmark-timer.git@main#egg=benchmark-timer
Применение
Пример одной итерации
from benchmark_timer import BenchmarkTimer import time with BenchmarkTimer(name="MySimpleCode") as tm, tm.single_iteration(): time.sleep(.3)
Выход:
Benchmarking MySimpleCode... MySimpleCode benchmark: n_iters=1 avg=0.300881s std=0.000000s range=[0.300881s~0.300881s]
Пример нескольких итераций
from benchmark_timer import BenchmarkTimer import time with BenchmarkTimer(name="MyTimedCode", print_iters=True) as tm: for timing_iteration in tm.iterations(n=5, warmup=2): with timing_iteration: time.sleep(.1) print("\n===================\n") print("List of timings: ", list(tm.timings.values()))
Выход:
Benchmarking MyTimedCode... [MyTimedCode] iter=0 took 0.099755s (warmup) [MyTimedCode] iter=1 took 0.100476s (warmup) [MyTimedCode] iter=2 took 0.100189s [MyTimedCode] iter=3 took 0.099900s [MyTimedCode] iter=4 took 0.100888s MyTimedCode benchmark: n_iters=3 avg=0.100326s std=0.000414s range=[0.099900s~0.100888s] =================== List of timings: [0.10018850000000001, 0.09990049999999995, 0.10088760000000008]
import time
start_time = time.time()
Вы также можете использовать time.clock
напишите свою программу здесь.
time_elapsed = time.time() - start_time
time.time () дает нам новое время компьютера.
В 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)
Лучше использовать timeit просто: (он запускает несколько прогонов для одной и той же команды и дает вам результаты).
Пример приведен ниже:
%timeit import pandas as pd
Единственный способ, которым я могу думать, - это использовать time.time()
,
import time
start = time.time()
sleep(5) #just to give it some delay to show it working
finish = time.time()
elapsed = finish - start
print(elapsed)
Надеюсь, что это поможет.
В дополнение к %timeit
в ipython вы также можете использовать %%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 таким же образом, просто положить магию %%timeit
в начале ячейки.