Измерить время, прошедшее в 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 в начале ячейки.

Другие вопросы по тегам