Как измерить прошедшее время в Python?

Я хочу начать отсчет времени где-нибудь в моем коде, а затем получить прошедшее время, чтобы измерить время, необходимое для выполнения нескольких функций. Я думаю, что неправильно использую модуль timeit, но документы меня просто сбивают с толку.

import timeit

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

person gilbert8    schedule 10.09.2011    source источник
comment
timeit.timeit () выводит время, необходимое для выполнения его аргумента, который по умолчанию передается. вместо этого вы должны использовать start = time.time () end = time.time ()   -  person AKludges    schedule 31.03.2021


Ответы (37)


Если вы просто хотите измерить время, прошедшее между двумя точками, вы можете использовать time.time():

import time

start = time.time()
print("hello")
end = time.time()
print(end - start)

Это дает время выполнения в секундах.

Другой вариант, начиная с версии 3.3, может заключаться в использовании perf_counter или _ 4_, в зависимости от ваших требований. До версии 3.3 рекомендовалось использовать time.clock (спасибо Янтарь). Однако в настоящее время он устарел:

В Unix вернуть текущее время процессора в виде числа с плавающей запятой, выраженного в секундах. Точность и, по сути, само определение значения «процессорного времени» зависит от одноименной функции Си.

В Windows эта функция возвращает часы настенных часов, прошедшие с момента первого вызова этой функции, в виде числа с плавающей запятой на основе функции Win32 QueryPerformanceCounter(). Разрешение обычно лучше одной микросекунды.

Не рекомендуется, начиная с версии 3.3: поведение этой функции зависит от платформы: вместо этого используйте perf_counter() или process_time(), в зависимости от ваших требований, чтобы иметь четко определенное поведение.

person NPE    schedule 10.09.2011
comment
а для микросекунд используйте datetime.time () - person Inca; 10.09.2011
comment
(Для измерения производительности на самом деле предпочтительнее использовать time.clock(), поскольку на него нельзя повлиять, если системные часы испорчены, но .time() в основном выполняет ту же цель.) - person Amber; 10.09.2011
comment
Я думаю, что python -mtimeit намного лучше, поскольку он запускается больше раз и построен как собственный способ измерения времени в python - person Visgean Skeloru; 04.02.2014
comment
Есть ли хороший способ преобразовать результирующее время выполнения в секундах во что-то вроде HH: MM :: SS? - person Danijel; 04.02.2016
comment
@Amber: time.clock() значение (что измеряется) и его точность и точность (разрешение) различаются между платформами. Документы больше не рекомендуют time.clock() для сравнительного анализа. Вместо этого можно использовать timeit.default_timer(). - person jfs; 06.04.2016
comment
@ Данижел: print(timedelta(seconds=execution_time)). Хотя это отдельный вопрос. - person jfs; 06.04.2016
comment
time.clock () у меня не работал. См. Ответ @JF Себастьяна timeit - person AlejandroVD; 09.05.2016
comment
Я предпочитаю это. Документ Timeit слишком запутан. from datetime import datetime startTime= datetime.now() # INSERT YOUR CODE timeElapsed=datetime.now()-startTime print('Time elpased (hh:mm:ss.ms) {}'.format(timeElapsed)) - person user1761806; 14.08.2017
comment
time.clock () устарел в Python 3.3 docs.python.org /3.3/library/time.html#time.clock - person noah; 06.06.2019
comment
@VisgeanSkeloru Но иногда вам просто нужно время, которое конкретная команда заняла в конкретном экземпляре, а не профилирование. В конце концов, запуск его n раз для повышения точности занимает в n раз больше времени. Что лучше, зависит от ситуации. - person RoG; 06.09.2019
comment
time.time() - плохая идея, потому что системные часы можно сбросить, что заставит вас вернуться в прошлое. time.monotonic() позаботится об этом (монотонный = он идет только вперед). time.perf_counter() также монотонный, но имеет еще более высокую точность, поэтому его рекомендуется использовать для настенных часов. - person xjcl; 31.05.2020
comment
Функция time.clock() была удалена после того, как она устарела с Python 3.3. Вместо этого можно использовать time.perf_counter() или time.process_time(). Ссылка: stackoverflow.com/a/58569410/6701627 - person thepunitsingh; 08.12.2020

Используйте timeit.default_timer вместо timeit.timeit. Первый автоматически обеспечивает лучшие часы, доступные на вашей платформе и версии Python:

from timeit import default_timer as timer

start = timer()
# ...
end = timer()
print(end - start) # Time in seconds, e.g. 5.38091952400282

timeit.default_timer назначается time.time () или времени .clock () в зависимости от ОС. В Python 3.3+ default_timer равен time.perf_counter () на всех платформах. См. Python - time.clock () vs. time.time () - точность?

Смотрите также:

person jfs    schedule 13.09.2014
comment
Отличный ответ - использование timeit даст гораздо более точные результаты, поскольку он автоматически учитывает такие вещи, как сборка мусора и различия ОС. - person lkgarrison; 11.12.2016
comment
Это дает время в мс или секундах? - person Katie; 08.02.2017
comment
@KhushbooTiwari за доли секунды. - person jfs; 08.02.2017
comment
Я думаю, что эту заметку из официальной документации нужно добавить default_timer() measurations can be affected by other programs running on the same machine, so the best thing to do when accurate timing is necessary is to repeat the timing a few times and use the best time. The -r option is good for this; the default of 3 repetitions is probably enough in most cases. On Unix, you can use time.clock() to measure CPU time. - person KGS; 06.07.2017
comment
@KGS: Измерение эффективности очень сложно в некотором роде (легко ввести себя в заблуждение). Есть много других замечаний, которые могут быть здесь уместны. Переходите по ссылкам в ответе. Возможно, вас также заинтересует perf модуль (на момент ответа не существовавший), который предоставляет тот же интерфейс, но иногда отличается от решений модуля timeit о том, как измерять временную производительность. - person jfs; 06.07.2017
comment
Мне не нравится, как происходил импорт. from timeit импортировать default_timer как таймер. Заблудился при чтении кода. Могло бы быть яснее без таймера as. - person Basil Musa; 22.10.2017
comment
Краткая лямбда: `` lang-python from timeit import default_timer as timer timed = lambda f, s = None: (f (), round (timer () - s, 3)) if s else timed (f, timer () ) (результат, истек) = время (некоторая_функция) `` - person Tapomay; 26.02.2020

Только Python 3:

Поскольку time.clock () устарел в Python 3.3, вы захотите использовать time.perf_counter() для общесистемной синхронизации, или time.process_time() для синхронизации всего процесса, как вы раньше используйте time.clock():

import time

t = time.process_time()
#do some stuff
elapsed_time = time.process_time() - t

Новая функция process_time не будет включать время, прошедшее во время сна.

person Pierre Prinetti    schedule 30.01.2014
comment
Используйте timeit.default_timer вместо time.perf_counter. Первый выберет подходящий таймер для измерения производительности времени, настроенного для вашей платформы и версии Python. process_time() не включает время во время сна, и поэтому нецелесообразно измерять прошедшее время. - person jfs; 22.02.2015
comment
Я использую реализацию, предложенную Пьером, указаны ли значения в секундах? - person ugotchi; 12.08.2016
comment
Этот ответ кажется не по теме (ну, вопрос не был очень конкретным). Есть два измерения времени: время настенных часов между двумя точками, потребление процессора процессом. - person Franklin Piat; 26.07.2019
comment
@fjs timeit.default_timer использует time.perf_counter в Python ›= 3.3 docs.python.org/ 3 / library / timeit.html # timeit.default_timer. - person ruohola; 05.02.2021

Время измерения в секундах:

from timeit import default_timer as timer
from datetime import timedelta

start = timer()
end = timer()
print(timedelta(seconds=end-start))

Вывод:

0:00:01.946339
person Gal Bracha    schedule 19.03.2019
comment
Это наиболее краткий ответ с максимально чистым результатом. - person Dave Liu; 31.05.2020

Учитывая функцию, которую вы хотите использовать,

test.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. Не помещайте операторы печати в функцию, которую вы хотите отсчитать; в противном случае измеренное время будет зависеть от скорость терминала.

person unutbu    schedule 10.09.2011

Это интересно сделать с помощью диспетчера контекста, который автоматически запоминает время начала при входе в блок with, а затем фиксирует время окончания при выходе из блока. С помощью небольшой уловки вы даже можете получить текущий счет прошедшего времени внутри блока с помощью той же функции диспетчера контекста.

В основной библиотеке этого нет (но, вероятно, должно быть). Оказавшись на месте, вы можете делать такие вещи, как:

with elapsed_timer() as elapsed:
    # some lengthy code
    print( "midpoint at %.2f seconds" % elapsed() )  # time so far
    # other lengthy code

print( "all done at %.2f seconds" % elapsed() )

Вот код contextmanager, достаточный для решения этой задачи:

from contextlib import contextmanager
from timeit import default_timer

@contextmanager
def elapsed_timer():
    start = default_timer()
    elapser = lambda: default_timer() - start
    yield lambda: elapser()
    end = default_timer()
    elapser = lambda: end-start

И немного исполняемого демонстрационного кода:

import time

with elapsed_timer() as elapsed:
    time.sleep(1)
    print(elapsed())
    time.sleep(2)
    print(elapsed())
    time.sleep(3)

Обратите внимание, что по замыслу этой функции возвращаемое значение elapsed() фиксируется при выходе из блока, и последующие вызовы возвращают ту же продолжительность (около 6 секунд в этом игрушечном примере).

person gojomo    schedule 04.05.2015
comment
Другой пример диспетчера контекста: dabeaz.blogspot.fr/2010 / 02 / - person Jérôme; 03.05.2016
comment
Хороший пример @ Jérôme - я адаптировал его как другой ответ - stackoverflow.com/a/41408510/243392 - person Brian Burns; 31.12.2016

Я предпочитаю это. timeit документ слишком запутан.

from datetime import datetime 

start_time = datetime.now() 

# INSERT YOUR CODE 

time_elapsed = datetime.now() - start_time 

print('Time elapsed (hh:mm:ss.ms) {}'.format(time_elapsed))

Обратите внимание, что здесь не происходит никакого форматирования, я просто написал hh:mm:ss в распечатке, чтобы можно было интерпретировать time_elapsed

person user1761806    schedule 14.08.2017
comment
Мне сказали, что timeit вычисляет время процессора, учитывает ли datetime также используемое время процессора? Это одно и то же? - person Sreehari R; 29.12.2017
comment
Таким образом измерять прошедшее время рискованно, потому что datetime.now () может меняться между двумя вызовами по таким причинам, как синхронизация сетевого времени, переход на летнее время или пользователь, вращающий часы. - person user1318499; 22.07.2019
comment
Из ответа Шитала Шаха: Во-первых, если вы обсуждаете между timeit и time.time, timeit имеет два преимущества: timeit выбирает лучший таймер, доступный в вашей ОС и версии Python. timeit отключает сборку мусора, однако это не то, что вам нужно или не нужно. - person mic; 01.08.2020

Вот еще один способ сделать это:

>> from pytictoc import TicToc
>> t = TicToc() # create TicToc instance
>> t.tic() # Start timer
>> # do something
>> t.toc() # Print elapsed time
Elapsed time is 2.612231 seconds.

По сравнению с традиционным способом:

>> from time import time
>> t1 = time()
>> # do something
>> t2 = time()
>> elapsed = t2 - t1
>> print('Elapsed time is %f seconds.' % elapsed)
Elapsed time is 2.612231 seconds.

Установка:

pip install pytictoc

Дополнительные сведения см. На странице PyPi.

person Mingwei He    schedule 08.07.2019
comment
Было бы хорошо объяснить преимущество использования этой библиотеки перед другими подходами. - person hlg; 08.07.2019
comment
Вложенная функциональность фактически не работает. Я открыл проблему с описанием проблемы в коде, но репо не поддерживалось в течение года, поэтому я не ожидал изменений. - person PetarMI; 10.07.2019
comment
Я считаю, что вложение немного сбивает с толку. Если бы я наткнулся на t.tic() погребенный в коде, разработчик должен был бы составить мысленный список того, где в серии я должен этого ожидать. Вы замечаете, что устраиваете гнезда или просто устраиваете несколько тиктоков? - person ScottieB; 17.10.2019
comment
@PetarMI: К вашему сведению, я только что исправил проблему с ttictoc. У меня был довольно беспорядок, но теперь все должно быть хорошо. - person H. Sánchez; 06.04.2020
comment
@hlg Если я правильно помню, MATLAB использует функции с похожими именами для временного материала. Итак, я предполагаю, что преимущество заключается в сходстве для людей, которым это понравилось в MATLAB, но которые перешли на Python. - person Henri; 19.11.2020

Вот мои выводы после того, как я прочитал здесь много хороших ответов, а также несколько других статей.

Во-первых, если вы спорите между timeit и time.time, у timeit есть два преимущества:

  1. timeit выбирает лучший таймер, доступный для вашей ОС и версии Python.
  2. timeit отключает сборку мусора, однако это не то, что вам нужно или не нужно.

Теперь проблема в том, что timeit не так просто использовать, потому что он требует настройки, и все становится некрасиво, когда у вас есть куча импорта. В идеале вам просто нужен декоратор или используйте with блок и измеряйте время. К сожалению, для этого нет ничего встроенного, поэтому у вас есть два варианта:

Вариант 1. Используйте библиотеку бюджета времени

timebudget - это универсальная и очень простая библиотека, которую можно использовать всего в одной строке кода после установки pip.

@timebudget  # Record how long this function takes
def my_method():
    # my code

Вариант 2. Используйте мой небольшой модуль

Ниже я создал небольшой служебный модуль синхронизации под названием Timing.py . Просто перетащите этот файл в свой проект и начните им пользоваться. Единственная внешняя зависимость - это runstats, опять же небольшого размера.

Теперь вы можете задать время для любой функции, просто поставив перед ней декоратор:

import timing

@timing.MeasureTime
def MyBigFunc():
    #do something time consuming
    for i in range(10000):
        print(i)

timing.print_all_timings()

Если вы хотите отследить часть кода, просто поместите ее в блок with:

import timing

#somewhere in my code

with timing.MeasureBlockTime("MyBlock"):
    #do something time consuming
    for i in range(10000):
        print(i)

# rest of my code

timing.print_all_timings()

Преимущества:

Есть несколько полуобеспеченных версий, поэтому я хочу выделить несколько основных моментов:

  1. Используйте таймер из timeit вместо time.time по причинам, описанным ранее.
  2. Вы можете отключить сборщик мусора на время, если хотите.
  3. Декоратор принимает функции с именованными или безымянными параметрами.
  4. Возможность отключения печати во время блока (используйте with timing.MeasureBlockTime() as t, а затем t.elapsed).
  5. Возможность держать gc включенным для синхронизации блока.
person Shital Shah    schedule 12.09.2018
comment
Относительно возможности отключения печати во время блока (используйте with utils.MeasureBlockTime() as t, а затем t.elapsed): это не работает как есть, поскольку t это None. Я думаю, что __enter__ нужно вернуть self, и чтобы отключить печать, мы должны построить его как utils.MeasureBlockTime(no_print=True). - person mic; 01.08.2020
comment
@mic - спасибо, что указали на это. Я обновил ответ этим и несколькими другими улучшениями. - person Shital Shah; 02.08.2020

Использование time.time для измерения выполнения дает вам общее время выполнения ваших команд, включая время, затраченное другими процессами на вашем компьютере. Это время, когда пользователь замечает, но это нехорошо, если вы хотите сравнить разные фрагменты кода / алгоритмы / функции / ...

Дополнительная информация о timeit:

Если вы хотите глубже понять профилирование:

Обновление: я много использовал http://pythonhosted.org/line_profiler/ во время в прошлом году и считаю его очень полезным и рекомендую использовать его вместо модуля профиля Pythons.

person rocksportrocker    schedule 10.09.2011

Самый простой способ рассчитать продолжительность операции:

import time

start_time = time.monotonic()

<operations, programs>

print('seconds: ', time.monotonic() - start_time)

Официальные документы здесь.

person Wojciech Moszczyński    schedule 30.05.2020
comment
@ user1318499 это не значит, что он возвращает отрицательные значения, он может возвращать более низкое значение, чем предыдущий вызов. docs.python.org/3/library/time.html#time. время - person Paolo; 14.04.2021

Модули 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), и это можно сделать с любым модулем.

Получив файл статистики, вы можете запустить модуль 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)

Фиктивный пример мало что дает, но дает представление о том, что можно сделать. Лучшее в этом подходе - то, что мне не нужно редактировать какой-либо из моего существующего кода, чтобы получить эти числа и, очевидно, помочь с профилированием.

person sanchitarora    schedule 26.12.2013
comment
Все это нормально, но AFAICT по-прежнему измеряет время процессора, а не время настенных часов. - person ShreevatsaR; 10.04.2014
comment
На самом деле есть некоторая путаница; похоже, что cProfile по умолчанию смотрит на время на настенных часах. Я поддержал ваш ответ. - person ShreevatsaR; 10.04.2014
comment
К сведению: если вы получили python -m pstats timeStats.profile ValueError: bad marshal data (unknown type code), проверьте свою версию Python, которую вы используете. Я получил это, когда запустил python3 -m cProfile... и python -m pstats. Моя ошибка, но меня поймали на секунду, поэтому я хотел поделиться don't forget consistency. знак равно - person JayRizzo; 26.10.2018

Вот еще один диспетчер контекста для кода времени -

Использование:

from benchmark import benchmark

with benchmark("Test 1+1"):
    1+1
=>
Test 1+1 : 1.41e-06 seconds

или, если вам нужна временная стоимость

with benchmark("Test 1+1") as b:
    1+1
print(b.time)
=>
Test 1+1 : 7.05e-07 seconds
7.05233786763e-07

benchmark.py:

from timeit import default_timer as timer

class benchmark(object):

    def __init__(self, msg, fmt="%0.3g"):
        self.msg = msg
        self.fmt = fmt

    def __enter__(self):
        self.start = timer()
        return self

    def __exit__(self, *args):
        t = timer() - self.start
        print(("%s : " + self.fmt + " seconds") % (self.msg, t))
        self.time = t

По материалам http://dabeaz.blogspot.fr/2010/02/context-manager-for-timing-benchmarks.html

person Brian Burns    schedule 31.12.2016

Вот крошечный класс таймера, который возвращает строку «чч: мм: сс»:

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
person Danijel    schedule 04.02.2016
comment
А теперь с f-строками и format specifications включено: time_str = f"{h:02d}:{m:02d}:{s:02d}" - person howdoicode; 24.01.2021

Используйте модуль профилировщика. Это дает очень подробный профиль.

import profile
profile.run('main()')

он выводит что-то вроде:

          5 function calls in 0.047 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.000    0.000 :0(exec)
        1    0.047    0.047    0.047    0.047 :0(setprofile)
        1    0.000    0.000    0.000    0.000 <string>:1(<module>)
        0    0.000             0.000          profile:0(profiler)
        1    0.000    0.000    0.047    0.047 profile:0(main())
        1    0.000    0.000    0.000    0.000 two_sum.py:2(twoSum)

Я нашел это очень информативным.

person Leonid Ganeline    schedule 18.07.2017
comment
Что такое main()? Было бы более полезно, если бы вы могли предоставить простой пример кода. - person not2qubit; 26.09.2018

(Только с Ipython) вы можете использовать % timeit для измерить среднее время обработки:

def foo():
    print "hello"

а потом:

%timeit foo()

результат будет примерно таким:

10000 loops, best of 3: 27 µs per loop
person Eyal Ch    schedule 24.11.2014
comment
Стоит отметить, что в% timeit можно передавать флаги, например -n указывает, сколько раз код должен быть повторен. - person raacer; 15.12.2016

Мне нравится простой (python 3):

from timeit import timeit

timeit(lambda: print("hello"))

Вывод составляет микросекунды для одного выполнения:

2.430883963010274

Объяснение: timeit по умолчанию выполняет анонимную функцию 1 миллион раз, и результат отображается в секундах. Следовательно, результат для 1 однократного выполнения будет такой же, но в среднем за микросекунды.


Для медленных операций добавьте меньшее количество итераций, иначе вы можете ждать бесконечно:

import time

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

Вывод всегда составляет секунды для общего количества итераций:

1.5015795179999714
person David    schedule 18.06.2019
comment
что вы подразумеваете под выводом? timeit пишет в stdout? - person Harry Moreno; 03.10.2020
comment
Нет. Я имею ввиду возвращаемое значение. - person David; 05.10.2020

на python3:

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

элегантный и короткий.

person DmitrySemenov    schedule 15.01.2016
comment
что это? РС? - person KIC; 11.09.2019
comment
@KIC Это в секундах. - person Guimoute; 07.06.2020

Еще один способ использовать timeit:

from timeit import timeit

def func():
    return 1 + 1

time = timeit(func, number=1)
print(time)
person raacer    schedule 15.12.2016

Чтобы получить представление о рекурсивном вызове каждой функции, выполните:

%load_ext snakeviz
%%snakeviz

Достаточно взять эти 2 строки кода из записной книжки Jupyter и создать красивую интерактивную диаграмму. Например:

введите описание изображения здесь

Вот код. Опять же, две строки, начинающиеся с %, являются единственными дополнительными строками кода, необходимыми для использования 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.

person Guillaume Chevalier    schedule 14.06.2019

Что-то вроде супер позднего ответа, но, возможно, для кого-то это служит какой-то цели. Я считаю, что это очень чистый способ сделать это.

import time

def timed(fun, *args):
    s = time.time()
    r = fun(*args)
    print('{} execution took {} seconds.'.format(fun.__name__, time.time()-s))
    return(r)

timed(print, "Hello")

Имейте в виду, что print - это функция в Python 3, а не в Python 2.7. Однако он работает с любой другой функцией. Ваше здоровье!

person Andreas Herman    schedule 14.08.2017
comment
Как я могу напечатать очень маленькое время? Я как бы всегда получаю 0,0 секунды - person Otieno Rowland; 27.11.2017
comment
Вы можете превратить это в декоратора; мне это кажется даже лучше. - person Daniel Moskovich; 10.10.2018

Вот довольно хорошо документированный декоратор с полным набором подсказок, который я использую как общую утилиту:

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)

Выход:

takes_long: 4.942629056s
True

Доктесты можно проверить с помощью:

$ python3 -m doctest --verbose -o=ELLIPSIS timer.py

И тип подсказывает:

$ mypy timer.py
person ruohola    schedule 01.06.2020
comment
Это супер круто, спасибо, что поделились. Я не встречал библиотеки набора текста или нелокального ключевого слова - интересно находить новые вещи, о которых можно узнать. Я не могу понять это: Callable[[AnyF], AnyF]. Что это значит? - person Danny; 03.06.2020
comment
@Danny Вверху я определил псевдоним типа AnyF для обозначения Callable[..., Any], поэтому AnyF - это функция, которая может принимать любое количество аргументов любого типа и возвращать что угодно. Таким образом, Callable[[AnyF], AnyF] расширится до Callable[[Callable[..., Any]], Callable[..., Any]]. Это тип возвращаемого значения timer или полный тип decorator. Это функция, которая принимает в качестве единственного аргумента любую функцию и возвращает любой вид функции. - person ruohola; 03.06.2020
comment
Спасибо за объяснение! Я все еще пытаюсь полностью погрузиться в внутренности декораторов. Это очень помогло! - person Danny; 03.06.2020

Вы можете использовать timeit.

Вот пример того, как протестировать naive_func, который принимает параметр, с помощью Python REPL:

>>> import timeit                                                                                         

>>> def naive_func(x):                                                                                    
...     a = 0                                                                                             
...     for i in range(a):                                                                                
...         a += i                                                                                        
...     return a                                                                                          

>>> def wrapper(func, *args, **kwargs):                                                                   
...     def wrapper():                                                                                    
...         return func(*args, **kwargs)                                                                  
...     return wrapper                                                                                    

>>> wrapped = wrapper(naive_func, 1_000)                                                                  

>>> timeit.timeit(wrapped, number=1_000_000)                                                              
0.4458435332577161  

Вам не нужна функция-оболочка, если функция не имеет параметров.

person Vlad Bezden    schedule 19.06.2017
comment
lambda был бы более лаконичным: print(timeit.timeit(lambda: naive_func(1_000), number=1_000_000)) - person Ciro Santilli 新疆再教育营六四事件ۍ 04.09.2018

Мы также можем преобразовать время в удобочитаемое время.

import time, datetime

start = time.clock()

def num_multi1(max):
    result = 0
    for num in range(0, 1000):
        if (num % 3 == 0 or num % 5 == 0):
            result += num

    print "Sum is %d " % result

num_multi1(1000)

end = time.clock()
value = end - start
timestamp = datetime.datetime.fromtimestamp(value)
print timestamp.strftime('%Y-%m-%d %H:%M:%S')
person Kamlesh Verma    schedule 17.09.2016

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  

Плюсы и минусы этой функции в том, что вам не нужно передавать время начала

person Myeongsik Joo    schedule 20.10.2020

Я сделал для этого библиотеку, если вы хотите измерить функцию, вы можете просто сделать это так


from pythonbenchmark import compare, measure
import time

a,b,c,d,e = 10,10,10,10,10
something = [a,b,c,d,e]

@measure
def myFunction(something):
    time.sleep(0.4)

@measure
def myOptimizedFunction(something):
    time.sleep(0.2)

myFunction(input)
myOptimizedFunction(input)

https://github.com/Karlheinzniebuhr/pythonbenchmark

person Karl    schedule 04.05.2015

Как измерить время между двумя операциями. Сравните время двух операций.

import time

b = (123*321)*123
t1 = time.time()

c = ((9999^123)*321)^123
t2 = time.time()

print(t2-t1)

7.987022399902344e-05

person Wojciech Moszczyński    schedule 17.09.2020

Хотя в вопросе это строго не задается, довольно часто требуется простой и единообразный способ постепенного измерения времени, прошедшего между несколькими строками кода.

Если вы используете Python 3.8 или выше, вы можете использовать выражения присваивания (он же оператор моржа), чтобы добиться этого довольно элегантным способом:

import time

start, times = time.perf_counter(), {}

print("hello")
times["print"] = -start + (start := time.perf_counter())

time.sleep(1.42)
times["sleep"] = -start + (start := time.perf_counter())

a = [n**2 for n in range(10000)]
times["pow"] = -start + (start := time.perf_counter())

print(times)

=>

{'print': 2.193450927734375e-05, 'sleep': 1.4210970401763916, 'power': 0.005671024322509766}
person Lee Netherton    schedule 11.02.2021

Этот уникальный подход на основе классов предлагает печатаемое строковое представление, настраиваемое округление и удобный доступ к истекшему времени в виде строки или числа с плавающей запятой. Он был разработан с помощью Python 3.7.

import datetime
import timeit


class Timer:
    """Measure time used."""
    # Ref: https://stackoverflow.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
person Acumenus    schedule 14.09.2019

Измеряйте время выполнения небольших фрагментов кода.

Единица времени: измеряется в секундах с плавающей запятой.

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!

person Aditya Patnaik    schedule 25.04.2020

В качестве лямбды получите прошедшее время и отметки времени:

import datetime
t_set = lambda: datetime.datetime.now().astimezone().replace(microsecond=0)
t_diff = lambda t: str(t_set() - 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'
>>> 
person ingyhere    schedule 21.03.2021

Если вы хотите иметь возможность удобно синхронизировать функции, вы можете использовать простой декоратор:

def timing_decorator(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        original_return_val = func(*args, **kwargs)
        end = time.time()
        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, он будет печатать, сколько времени это заняло, и имя функции, для которой требуется время.

person Daniel Giger    schedule 01.05.2020
comment
Есть ли способ сделать это Python2.x без необходимости импортировать print_function из __future__? Я пытался использовать join, но не понимаю его достаточно хорошо, чтобы заставить его работать. - person frakman1; 08.08.2020
comment
ОБНОВИТЬ. Я понял это и использовал это: print(''.join(["time elapsed in ",(func.__name__),": ",str(end - start)])) - person frakman1; 08.08.2020

на основе решения contextmanager, предоставленного https://stackoverflow.com/a/30024601/5095636, ниже - бесплатная версия лямбда , поскольку 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
person Xiang ZHU    schedule 05.05.2020

Модуль 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)
person Shaboti    schedule 18.11.2019

Время также можно измерить с помощью магической функции% timeit следующим образом:

%timeit -t -n 1 print("hello")

n 1 предназначен для выполнения функции только 1 раз.

person Punit Vara    schedule 26.02.2020

Помимо %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 таким же образом, просто введите magic %%timeit в начале ячейки.

person vishes_shell    schedule 28.11.2018

person    schedule
comment
Не делайте этого, потому что time.time() не обязательно увеличивается равномерно. Вы можете получить отрицательную продолжительность, если есть корректировка летнего времени или что-то еще. Замените time.time() на time.monotonic(). - person user1318499; 19.06.2020