web-dev-qa-db-pt.com

Medir o tempo decorrido em Python?

O que eu quero é começar a contar o tempo em algum lugar no meu código e depois obter o tempo passado, para medir o tempo que levou para executar poucas funções. Eu acho que estou usando o módulo timeit errado, mas os documentos são apenas confusos para mim.

import timeit

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

Se você quiser apenas medir o tempo decorrido entre dois pontos, você pode usar time.time() :

import time

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

Isso dá o tempo de execução em segundos.

Outra opção desde 3.3 pode ser usar perf_counter ou process_time , dependendo de suas necessidades. Antes de 3.3 era recomendado usar time.clock (obrigado Âmbar ). No entanto, está atualmente suspenso:

No Unix, retorne a hora atual do processador como um número de ponto flutuante Expresso em segundos. A precisão, e de fato a própria definição Do significado de “tempo do processador”, depende da função C Do mesmo nome.

No Windows, essa função retorna segundos de relógio de parede transcorridos desde a primeira chamada Para essa função, como um número de ponto flutuante, com base na função Win32 QueryPerformanceCounter(). A resolução é tipicamente Melhor que um microssegundo.

Reprovado desde a versão 3.3: O comportamento desta função depende Da plataforma: use perf_counter() ou process_time() em vez de, Dependendo de suas necessidades, para ter um poço comportamento definido.

1012
NPE

Use timeit.default_timer em vez de timeit.timeit. O primeiro fornece o melhor relógio disponível em sua plataforma e versão do Python automaticamente:

from timeit import default_timer as timer

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

timeit.default_timer é atribuído a time.time () ou time.clock () dependendo do SO. No Python 3.3+ default_timer é time.perf_counter () em todas as plataformas. Veja Python - time.clock () vs. time.time () - precisão?

Veja também:

420
jfs

Somente Python 3:

Uma vez que time.clock () está obsoleto a partir do Python 3.3 , você desejará usar time.perf_counter() para a temporização em todo o sistema, ou time.process_time() para a temporização em todo o processo, exatamente como você usou para usar time.clock():

import time

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

A nova função process_time não incluirá o tempo decorrido durante o sono.

99
Pierre Prinetti

Dada uma função que você gostaria de tempo,

test.py:

def foo(): 
    # print "hello"   
    return "hello"

a maneira mais fácil de usar timeit é chamá-lo na linha de comando:

% python -mtimeit -s'import test' 'test.foo()'
1000000 loops, best of 3: 0.254 usec per loop

Não tente usar time.time ou time.clock (ingenuamente) para comparar a velocidade das funções. Eles podem dar resultados enganosos .

PS. Não coloque instruções de impressão em uma função que você deseja cronometrar; caso contrário, o tempo medido dependerá da velocidade do terminal .

73
unutbu

Eu prefiro isso. timeit doc é muito confuso. 

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

Note que não há nenhuma formatação acontecendo aqui, eu apenas escrevi hh:mm:ss na impressão para que alguém possa interpretar time_elapsed

45
user1761806

É divertido fazer isso com um gerenciador de contexto que automaticamente lembra a hora de início na entrada de um bloco with, depois congela a hora final na saída do bloco. Com um pequeno truque, você pode até obter uma contagem de tempo decorrido dentro do bloco a partir da mesma função de gerenciador de contexto. 

A biblioteca principal não tem isso (mas provavelmente deveria). Uma vez no lugar, você pode fazer coisas como:

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

Aqui está o contextmanager code suficiente para fazer o truque:

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

E algum código de demonstração executável:

import time

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

Observe que, pelo design dessa função, o valor de retorno de elapsed() é congelado na saída de bloco e outras chamadas retornam a mesma duração (de cerca de 6 segundos neste exemplo de brinquedo). 

43
gojomo

O uso do time.time para medir a execução fornece o tempo total de execução de seus comandos, incluindo o tempo de execução gasto por outros processos em seu computador. É o tempo que o usuário percebe, mas não é bom se você quiser comparar diferentes trechos de código/algoritmos/funções/...

Mais informações sobre timeit:

Se você quiser uma visão mais profunda sobre o perfil:

Update: Eu usei http://pythonhosted.org/line_profiler/ muito durante o ano passado e achei muito útil e recomendo usá-lo em vez do módulo de perfil Pythons.

24
rocksportrocker

Aqui está uma pequena classe de timer que retorna a string "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

Uso: 

# 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
18
Danijel

Os módulos python cProfile e pstats oferecem grande suporte para medir o tempo decorrido em certas funções sem precisar adicionar nenhum código ao redor das funções existentes.

Por exemplo, se você tiver um script 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()

Para executar o profiler e gerar estatísticas para o arquivo, você pode simplesmente executar:

python -m cProfile -o timeStats.profile timeFunctions.py

O que isso está fazendo é usar o módulo cProfile para criar o perfil de todas as funções em timeFunctions.py e coletar as estatísticas no arquivo timeStats.profile. Note que não precisamos adicionar nenhum código ao módulo existente (timeFunctions.py) e isso pode ser feito com qualquer módulo.

Depois de ter o arquivo de estatísticas, você pode executar o módulo pstats da seguinte maneira:

python -m pstats timeStats.profile

Isso executa o navegador de estatísticas interativas, que oferece muitas funcionalidades interessantes. Para o seu caso de uso específico, você pode apenas verificar as estatísticas da sua função. Em nosso exemplo, verificar as estatísticas de ambas as funções mostra o seguinte:

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)

O exemplo fictício não faz muito, mas dá uma idéia do que pode ser feito. A melhor parte sobre essa abordagem é que eu não tenho que editar qualquer um dos meus códigos existentes para obter esses números e, obviamente, ajudar com o perfil.

16
sanchitarora

Aqui está outro gerenciador de contexto para o código de tempo -

Uso: 

from benchmark import benchmark

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

ou, se você precisar do valor do tempo

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

Adaptado de http://dabeaz.blogspot.fr/2010/02/context-manager-for-timing-benchmarks.html

16
Brian Burns

Use o módulo de profiler. Dá um perfil muito detalhado.

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

ela produz algo como:

          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)

Eu achei muito informativo.

14
Leonid Ganeline

(Apenas com o Ipython) você pode usar % timeit para medir o tempo médio de processamento:

def foo():
    print "hello"

e depois: 

%timeit foo()

o resultado é algo como:

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

em python3:

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

elegante e curto.

9
DmitrySemenov

Mais ou menos como uma resposta posterior, mas talvez sirva a um propósito para alguém. Esta é uma maneira de fazer isso que eu acho super clean.

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

Tenha em mente que "print" é uma função do Python 3 e não do Python 2.7. No entanto, funciona com qualquer outra função. Felicidades!

9
Andreas Herman

Também podemos converter o tempo em tempo legível por humanos.

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')
6
Kamlesh Verma

Aqui estão minhas descobertas depois de passar por muitas boas respostas aqui, bem como alguns outros artigos.

Primeiro, você sempre quer usar timeit e não time.time (e em muitos casos, counter couns APIs) porque 

  1. timeit seleciona o melhor temporizador disponível no seu sistema operacional e na versão do Python. 
  2. timeit desativa a coleta de lixo, mas isso não é algo que você pode ou não querer.

Agora o problema é que o tempo não é tão simples de usar, porque precisa de configuração e as coisas ficam feias quando você tem um monte de importações. Idealmente, você quer apenas um decorador ou usar o bloco with e medir o tempo. Infelizmente não há nada embutido disponível para isso, então criei um módulo de utilidade pouco abaixo.

Módulo utilitário de temporização

# 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

Como funções de tempo

Agora você pode cronometrar qualquer função apenas colocando um decorador na frente dela:

import utils

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

Como codificar blocos de tempo

Se você quiser tempo parte do código, basta colocá-lo dentro de bloco 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

Vantagens

Existem várias versões half-backed flutuando, então quero destacar alguns destaques:

  1. Use temporizador de timeit em vez de time.time por razões descritas anteriormente.
  2. Desativar GC durante o tempo.
  3. O Decorator aceita funções com parâmetros nomeados ou não nomeados.
  4. Capacidade de desativar a impressão no tempo de bloqueio (use with utils.MeasureBlockTime() as t e, em seguida, t.elapsed).
  5. Capacidade de manter o gc ativado para o tempo de bloqueio.
6
Shital Shah

Mais uma maneira de usar timeit :

from timeit import timeit

def func():
    return 1 + 1

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

Eu fiz uma biblioteca para isso, se você quiser medir uma função, você pode fazer isso 


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

5
karlpy

Tempo de medição em segundos:

from timeit import default_timer as timer
from datetime import timedelta

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

Saída:

0:00:01.946339
5
Gal Bracha

Você pode usar o timeit.

Aqui está um exemplo de como testar o naive_func que usa o parâmetro usando o 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  

Você não precisa da função de invólucro se a função não tiver nenhum parâmetro. 

4
Vlad Bezden

A única maneira que posso pensar é usando 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)

Espero que ajude.

0
Trooper Z