Как измерить время, затрачиваемое между строками кода в Python?


98

Итак, в Java мы можем сделать Как измерить время, затрачиваемое функцией на выполнение

Но как это сделать в питоне? Чтобы измерить время начала и время окончания между строками кода? Что-то, что делает это:

import some_time_library

starttime = some_time_library.some_module()
code_tobe_measured() 
endtime = some_time_library.some_module()

time_taken = endtime - starttime

Ответы:


150

Если вы хотите измерить время процессора, можете использовать time.process_time()для Python 3.3 и выше:

import time
start = time.process_time()
# your code here    
print(time.process_time() - start)

Первый вызов включает таймер, а второй сообщает вам, сколько секунд прошло.

Также есть функция time.clock(), но она устарела с Python 3.3 и будет удалена в Python 3.8.

Существуют лучшие инструменты профилирования, такие как timeitи profile, однако time.process_time () будет измерять время процессора, и это то, о чем вы спрашиваете.

Если вы хотите вместо этого измерить время на настенных часах, используйте time.time().


52
Это не то, как вы используете time.clock()и time.clock()измеряет время ЦП в Unix, а время на стене в Windows. Лучше использовать time.time()там, где поведение не зависит от ОС. stackoverflow.com/questions/85451/…
Тим

4
Хорошее наблюдение, @ Тим. Однако в другом сообщении по тому же вопросу цитируется python doc on time.clock (), что «это функция для тестирования Python или алгоритмов синхронизации». Я думаю, это касается вопроса о том, что вы действительно хотите измерить.
Евгений Ямпольский

1
Очень плохо в time.time () то, что на него влияет синхронизация времени ntpdate и т. Д. Я бы сказал, что time.clock () будет единственной надежной альтернативой из-за этого
www.jensolsson.se

4
DeprecationWarning: time.clock has been deprecated in Python 3.3 and will be removed from Python 3.8: use time.perf_counter or time.process_time instead
ismailarilik 03

2
Хммм ... не уверен, что делаю не так. Я заменил # your code hereна time.sleep(10)и получил 0,0 секунды. Добавление for i in range(10000):/passдало те же результаты. При любых обстоятельствах, которые я пробовал, time.process_time()всегда возвращает одно и то же число. time.perf_counter()Тем не менее, я получил ожидаемые результаты, используя
biscuit314

56

Вы также можете использовать timeбиблиотеку:

import time

start = time.time()

# your code

# end

print(f'Time: {time.time() - start}')

1
@Hayat - этот метод возвращает время в виде числа с плавающей запятой, выраженного в секундах с начала эпохи в UTC. [ docs.python.org/3/library/time.html]
Анумой Сутрадхар

@AnumoySutradhar не совсем так, поскольку он вычитает эпоху из эпохи, вы получаете разницу во времени между двумя временами.
Наста

28

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

with CodeTimer():
   line_to_measure()
   another_line()
   # etc...

Что покажет следующее после завершения выполнения строк с отступом:

Code block took: x.xxx ms

ОБНОВЛЕНИЕ: теперь вы можете получить класс с помощью, pip install linetimerа затем from linetimer import CodeTimer. См. Этот проект GitHub .

Код для вышеуказанного класса:

import timeit

class CodeTimer:
    def __init__(self, name=None):
        self.name = " '"  + name + "'" if name else ''

    def __enter__(self):
        self.start = timeit.default_timer()

    def __exit__(self, exc_type, exc_value, traceback):
        self.took = (timeit.default_timer() - self.start) * 1000.0
        print('Code block' + self.name + ' took: ' + str(self.took) + ' ms')

Затем вы можете назвать блоки кода, которые хотите измерить:

with CodeTimer('loop 1'):
   for i in range(100000):
      pass

with CodeTimer('loop 2'):
   for i in range(100000):
      pass

Code block 'loop 1' took: 4.991 ms
Code block 'loop 2' took: 3.666 ms

И вложите их:

with CodeTimer('Outer'):
   for i in range(100000):
      pass

   with CodeTimer('Inner'):
      for i in range(100000):
         pass

   for i in range(100000):
      pass

Code block 'Inner' took: 2.382 ms
Code block 'Outer' took: 10.466 ms

Что касается timeit.default_timer(), он использует лучший таймер на основе версии ОС и Python, см. Этот ответ .


9

Я всегда предпочитаю проверять время в формате часов, минут и секунд (% H:% M:% S):

from datetime import datetime
start = datetime.now()
# your code
end = datetime.now()
time_taken = end - start
print('Time: ',time_taken) 

выход:

Time:  0:00:00.000019

3

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

import pandas as pd
start = pd.Timestamp.now()
# code
print(pd.Timestamp.now()-start)

Выход:

0 days 00:05:32.541600

Я бы рекомендовал использовать это, если точность времени не является самым важным, в противном случае используйте timeбиблиотеку:

%timeit pd.Timestamp.now() выходы 3,29 мкс ± 214 нс на цикл

%timeit time.time() выводит 154 нс ± 13,3 нс на цикл



1

Другой вариант - поместить код в функцию, а затем использовать декоратор для синхронизации. ( Источник ) Преимущество этого метода в том, что вы определяете таймер один раз и используете его с простой дополнительной строкой для каждой функции.

Сначала определите timerдекоратор:

import functools
import time

def timer(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.perf_counter()
        value = func(*args, **kwargs)
        end_time = time.perf_counter()
        run_time = end_time - start_time
        print("Finished {} in {} secs".format(repr(func.__name__), round(run_time, 3)))
        return value

    return wrapper

Затем используйте декоратор при определении функции:

@timer
def doubled_and_add(num):
    res = sum([i*2 for i in range(num)])
    print("Result : {}".format(res))

Давай попробуем:

doubled_and_add(100000)
doubled_and_add(1000000)

Выход:

Result : 9999900000
Finished 'doubled_and_add' in 0.0119 secs
Result : 999999000000
Finished 'doubled_and_add' in 0.0897 secs

Примечание: я не уверен, зачем использовать time.perf_counterвместо time.time. Комментарии приветствуются.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.