Измерьте время, прошедшее в Python

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

import timeit

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

Ответ 1

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

import time

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

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

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

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

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

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

Ответ 2

Используйте 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() или time.clock() в зависимости от ОС. На Python 3. 3+ default_timer - это time.perf_counter() на всех платформах. Смотрите Python - time.clock() против time.time() - точность?

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

Ответ 3

Только 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 не будет включать время, прошедшее во время сна.

Ответ 4

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

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

Ответ 5

Приятно это сделать с помощью контекстного менеджера, который автоматически запоминает время запуска при входе в блок 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 секунд в этом примере игрушек).

Ответ 6

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

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

Ответ 7

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

from timeit import default_timer as timer
from datetime import timedelta

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

Выход:

0:00:01.946339

Ответ 8

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

Больше информации о timeit:

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

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

Ответ 9

Вот крошечный класс таймера, который возвращает строку "hh: mm: ss":

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

Ответ 10

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

Например, если у вас есть python script 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)

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

Ответ 11

Здесь другой менеджер контекста для кода синхронизации -

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

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

Ответ 12

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

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)

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

Ответ 13

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

Во-первых, вы всегда хотите использовать timeit а не time.time (и во многих случаях API счетчиков перфорации), потому что

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

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

Служебный модуль Timing

# utils.py
from functools import wraps
import gc
import timeit

def MeasureTime(f):
    @wraps(f)
    def _wrapper(*args, **kwargs):
        gcold = gc.isenabled()
        gc.disable()
        start_time = timeit.default_timer()
        try:
            result = f(*args, **kwargs)
        finally:
            elapsed = timeit.default_timer() - start_time
            if gcold:
                gc.enable()
            print('Function "{}": {}s'.format(f.__name__, elapsed))
        return result
    return _wrapper

class MeasureBlockTime:
    def __init__(self,name="(block)", no_print = False, disable_gc = True):
        self.name = name
        self.no_print = no_print
        self.disable_gc = disable_gc
    def __enter__(self):
        if self.disable_gc:
            self.gcold = gc.isenabled()
            gc.disable()
        self.start_time = timeit.default_timer()
    def __exit__(self,ty,val,tb):
        self.elapsed = timeit.default_timer() - self.start_time
        if self.disable_gc and self.gcold:
            gc.enable()
        if not self.no_print:
            print('Function "{}": {}s'.format(self.name, self.elapsed))
        return False #re-raise any exceptions

Как рассчитать время

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

import utils

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

Как блокировать временные коды

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

import utils

#somewhere in my code

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

# rest of my code

преимущества

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

  1. Используйте таймер из timeit вместо time.time по причинам, описанным ранее.
  2. Отключить GC во время синхронизации.
  3. Декоратор принимает функции с именованными или безымянными параметрами.
  4. Возможность отключить печать во время блока (используйте with utils.MeasureBlockTime() as t а затем t.elapsed).
  5. Возможность держать gc включенным для синхронизации блока.

Ответ 14

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

def foo():
    print "hello"

а затем:

%timeit foo()

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

10000 loops, best of 3: 27 µs per loop

Ответ 15

на python3:

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

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

Ответ 16

Сейчас 2019 год. Давайте сделаем это кратким способом:

from ttictoc import TicToc
t = TicToc() ## TicToc("name")
t.tic();
# your code ...
t.toc();
print(t.elapsed)

Преимущества использования этого подхода вместо других:

  1. Краткий и прямой. программисту не требуется писать дополнительные переменные, такие как:
    t1 = время()
    t2 = время()
    истекло = t2 - t1
  2. С вложенностью
t = TicToc(nested=True)
t.tic()
some code1...
t.tic()
some code2...
t.tic()
some code3...
print(t.toc()) # Prints time for code 3 
print(t.toc()) # Prints time for code 2 with code 3
print(t.toc()) # Prints time for code 1 with code 2 and 3
  1. Сохраните названия своего тиктока.
t = TicToc("save user")
print(t.name)

Пожалуйста, обратитесь к этой ссылке для получения более подробных инструкций.

Ответ 17

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

from timeit import timeit

timeit(lambda: print("hello"))

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

2.430883963010274

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


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

import time

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

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

1.5015795179999714

Ответ 18

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

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")

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

Ответ 19

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

from timeit import timeit

def func():
    return 1 + 1

time = timeit(func, number=1)
print(time)

Ответ 20

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

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')

Ответ 21

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


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

Ответ 22

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

%load_ext snakeviz
%%snakeviz

Он просто берет эти две строки кода в блокноте Jupyter и создает красивую интерактивную диаграмму. Например:

enter image description here

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

Ответ 23

Вы можете использовать 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  

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

Ответ 24

Единственный способ, которым я могу думать, это использовать 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)

Надеюсь, что это поможет.

Ответ 25

Этот уникальный подход на основе классов предлагает печатное представление строки, настраиваемое округление и удобный доступ к прошедшему времени в виде строки или числа с плавающей запятой. Он был разработан с 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)))

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

>>> 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

Ответ 26

В дополнение к %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 в начале ячейки.

Ответ 27

Лучше использовать timeit просто: (он запускает несколько прогонов для одной и той же команды и дает вам результаты).

Пример приведен ниже:

%timeit import pandas as pd