Se você realmente deseja o equivalente direto, basta ligar tic = time.time()e toc = time.time(), print toc-tic, 'sec Elapsed'como o pessoal disse abaixo, porém, timeité mais robusto.
Joe Kington
Parece que consigo melhores resultados usando a abordagem de @JoeKington em conjunto com timeit.default_timer (), como este por exemplo:, tic = timeit.default_timer(); (U,S,V) = np.linalg.svd(A); toc = timeit.default_timer()então print toc-tic.
LittleO
1
A biblioteca pytictoc parece mais conveinente, a sintaxe é até um pouco mais organizada que ttictoc abaixo. pypi.org/project/pytictoc
FlorianH
Respostas:
172
Além do timeitque o ThiefMaster mencionou, uma maneira simples de fazer isso é apenas (após a importação time):
t = time.time()# do stuff
elapsed = time.time()- t
@eat: discordo respeitosamente. As pessoas têm usado o timecomando unix para medir tempos de execução de programas desde sempre, e esse método replica isso dentro do código Python. Não vejo nada de errado nisso, desde que seja a ferramenta certa para o trabalho. timeitnem sempre é isso, e um profiler é uma solução muito mais pesada para a maioria das necessidades
Eli Bendersky
4
Para a última linha, eu sugeriria print 'Elapsed: %.2f seconds % (time.time() - self.tstart)'. É difícil entender sem o% .2f. Obrigado pela ótima ideia.
Can Kavaklıoğlu
4
Isso parece muito conveniente à primeira vista, mas na prática requer que se indente o bloco de código desejado, o que pode ser bastante inconveniente dependendo do comprimento do bloco de código e do editor de escolha. Ainda uma solução elegante, que se comporta corretamente no caso de uso aninhado.
Stefan
1
Eu acho que você quer elapsed = t - time.time(), em vez de elapsed = time.time() - t. No último, decorrido será negativo. Eu sugeri essa mudança como uma edição.
rysqui
3
@rysqui - A hora atual não é sempre um número maior do que a hora anterior ? Eu acho que elapsed = time.time() - té a forma que sempre produz um valor positivo.
Scott Smith
32
Eu tive a mesma pergunta quando migrei para python do Matlab. Com a ajuda deste tópico, fui capaz de construir um análogo exato do Matlab tic()e toc()funções. Basta inserir o código a seguir na parte superior do seu script.
import timedefTicTocGenerator():# Generator that returns time differences
ti =0# initial time
tf = time.time()# final timewhileTrue:
ti = tf
tf = time.time()yield tf-ti # returns the time differenceTicToc=TicTocGenerator()# create an instance of the TicTocGen generator# This will be the main function through which we define both tic() and toc()def toc(tempBool=True):# Prints the time difference yielded by generator instance TicToc
tempTimeInterval =next(TicToc)if tempBool:print("Elapsed time: %f seconds.\n"%tempTimeInterval )def tic():# Records a time in TicToc, marks the beginning of a time interval
toc(False)
É isso aí! Agora estamos prontos para usar totalmente tic()e toc()exatamente como no Matlab. Por exemplo
Na verdade, isso é mais versátil do que as funções integradas do Matlab. Aqui, você pode criar outra instância do TicTocGeneratorpara controlar várias operações ou apenas para cronometrar as coisas de forma diferente. Por exemplo, enquanto cronometramos um script, agora podemos cronometrar cada parte do script separadamente, bem como o script inteiro. (Vou dar um exemplo concreto)
TicToc2=TicTocGenerator()# create another instance of the TicTocGen generatordef toc2(tempBool=True):# Prints the time difference yielded by generator instance TicToc2
tempTimeInterval =next(TicToc2)if tempBool:print("Elapsed time 2: %f seconds.\n"%tempTimeInterval )def tic2():# Records a time in TicToc2, marks the beginning of a time interval
toc2(False)
Agora você deve ser capaz de cronometrar duas coisas distintas: No exemplo a seguir, cronometramos o script total e partes de um script separadamente.
O melhor análogo absoluto de tic e toc seria simplesmente defini-los em python.
def tic():#Homemade version of matlab tic and toc functionsimport time
global startTime_for_tictoc
startTime_for_tictoc = time.time()def toc():import time
if'startTime_for_tictoc'in globals():print"Elapsed time is "+ str(time.time()- startTime_for_tictoc)+" seconds."else:print"Toc: start time not set"
Isso não se comportará corretamente no caso de uso aninhado de tice toc, que o Matlab suporta. Um pouco mais de sofisticação seria necessário.
Stefan
2
Implementei funções semelhantes em meu próprio código quando precisei de algum tempo básico. No entanto, eu removeria a parte import timeexterna de ambas as funções, já que pode levar algum tempo.
Bas Swinckels de
Se você insiste em usar essa técnica e precisa dela para lidar com tic / toc aninhado, faça do global uma lista e deixe-o ticempurrar e tocsair dela.
Ahmed Fasih
1
Também li em outro lugar que timeit.default_timer()é melhor do que time.time()porque time.clock()pode ser mais apropriado dependendo do sistema operacional
Miguel
@AhmedFasih É o que minha resposta faz, embora mais coisas possam ser melhoradas.
antonimmo
15
Normalmente, IPython de %time, %timeit, %prune %lprun(caso tenha line_profilerinstalado) satisfazer as minhas necessidades de perfis muito bem. No entanto, um caso de uso para tic-tocfuncionalidade semelhante surgiu quando tentei traçar o perfil de cálculos que eram dirigidos interativamente, ou seja, pelo movimento do mouse do usuário em uma GUI. Achei que enviar spam para tics e tocs nas fontes enquanto testava interativamente seria a maneira mais rápida de revelar os gargalos. Fui com a Timeraula de Eli Bendersky , mas não fiquei muito feliz, pois me obrigou a alterar a indentação do meu código, o que pode ser inconveniente em alguns editores e confunde o sistema de controle de versão. Além disso, pode haver a necessidade de medir o tempo entre pontos em diferentes funções, o que não funcionaria com owithdeclaração. Depois de tentar muita inteligência Python, aqui está a solução simples que achei que funcionou melhor:
from time import time
_tstart_stack =[]def tic():
_tstart_stack.append(time())def toc(fmt="Elapsed: %s s"):print fmt %(time()- _tstart_stack.pop())
Uma vez que isso funciona empurrando os tempos iniciais em uma pilha, funcionará corretamente para vários níveis de tics e tocs. Ele também permite alterar a string de formato da tocinstrução para exibir informações adicionais, o que eu gostei na Timeraula de Eli .
Por algum motivo, fiquei preocupado com a sobrecarga de uma implementação Python pura, então testei um módulo de extensão C também:
Isso é para MacOSX e omiti o código para verificar se lvlestá fora dos limites por questão de brevidade. Embora tictoc.res()produza uma resolução de cerca de 50 nanossegundos em meu sistema, descobri que o jitter de medir qualquer instrução Python está facilmente na faixa de microssegundos (e muito mais quando usado no IPython). Nesse ponto, a sobrecarga da implementação Python torna-se insignificante, de modo que pode ser usada com a mesma confiança da implementação C.
Descobri que a utilidade da tic-tocabordagem -é praticamente limitada a blocos de código que levam mais de 10 microssegundos para serem executados. Abaixo disso, estratégias de média como em timeitsão necessárias para obter uma medição fiel.
Acabei de criar um módulo [tictoc.py] para obter tic tocs aninhados, que é o que o Matlab faz.
from time import time
tics =[]def tic():
tics.append(time())def toc():if len(tics)==0:returnNoneelse:return time()-tics.pop()
E funciona assim:
from tictoc import tic, toc
# This keeps track of the whole process
tic()# Timing a small portion of code (maybe a loop)
tic()# -- Nested code here --# End
toc()# This returns the elapse time (in seconds) since the last invocation of tic()
toc()# This does the same for the first tic()
Devo avisar que isso pode não se comportar como desejado quando usado simultaneamente por mais de 1 módulo, uma vez que os módulos (AFAIK) se comportam como singletons.
antonimmo
3
Dê uma olhada no timeitmódulo. Não é realmente equivalente, mas se o código que você deseja cronometrar estiver dentro de uma função, você pode usá-lo facilmente.
Isso também pode ser feito usando um invólucro. Maneira muito geral de marcar o tempo.
O wrapper neste código de exemplo envolve qualquer função e imprime a quantidade de tempo necessária para executar a função:
def timethis(f):import time
def wrapped(*args,**kwargs):
start = time.time()
r = f(*args,**kwargs)print"Executing {0} took {1} seconds".format(f.func_name, time.time()-start)return r
return wrapped
@timethisdef thistakestime():for x in range(10000000):pass
thistakestime()
A função de wrapper, timethis, é chamada de decorador. Uma explicação um pouco mais detalhada, aqui: medium.com/pythonhive/…
Mircea
1
Mudei um pouco a resposta de @Eli Bendersky para usar o ctor __init__()e o dtor __del__()para fazer o tempo, para que possa ser usado de maneira mais conveniente sem recuar o código original:
Um problema com essa implementação é o fato de que timernão é excluída após a última chamada, se qualquer outro código segue após o forloop. Para obter o último valor do temporizador, deve-se excluir ou sobrescrever o timerafter the forloop, por exemplo, via timer = None.
bastelflp
1
@bastelflp Acabei de perceber que entendi mal o que você quis dizer ... Sua sugestão foi incorporada ao código agora. Obrigado.
Assim como o de Eli, ele pode ser usado como um gerenciador de contexto:
import time
withTimer('Count'):for i in range(0,10_000_000):pass
Resultado:
[Count]Elapsed:0.27 seconds
Também o atualizei para imprimir as unidades de tempo relatadas (segundos) e cortar o número de dígitos conforme sugerido por Can, e com a opção de também anexar a um arquivo de log. Você deve importar data e hora para usar o recurso de registro:
import time
import datetime
withTimer('Count','log.txt'):for i in range(0,10_000_000):pass
você pode simplesmente usar tic(), toc()e ninho-los como em Matlab
Alternativamente, você pode nomeá-los: tic(1), toc(1)ou tic('very-important-block'), toc('very-important-block')e temporizadores com nomes diferentes não irá interferir
importá-los dessa forma evita a interferência entre os módulos que o utilizam.
(aqui toc não imprime o tempo decorrido, mas o retorna.)
tic = time.time()
etoc = time.time()
,print toc-tic, 'sec Elapsed'
como o pessoal disse abaixo, porém,timeit
é mais robusto.tic = timeit.default_timer(); (U,S,V) = np.linalg.svd(A); toc = timeit.default_timer()
entãoprint toc-tic
.Respostas:
Além do
timeit
que o ThiefMaster mencionou, uma maneira simples de fazer isso é apenas (após a importaçãotime
):Tenho uma classe auxiliar que gosto de usar:
Ele pode ser usado como um gerenciador de contexto:
Às vezes, acho essa técnica mais conveniente do que
timeit
- tudo depende do que você deseja medir.fonte
time
comando unix para medir tempos de execução de programas desde sempre, e esse método replica isso dentro do código Python. Não vejo nada de errado nisso, desde que seja a ferramenta certa para o trabalho.timeit
nem sempre é isso, e um profiler é uma solução muito mais pesada para a maioria das necessidadesprint 'Elapsed: %.2f seconds % (time.time() - self.tstart)'
. É difícil entender sem o% .2f. Obrigado pela ótima ideia.elapsed = t - time.time()
, em vez deelapsed = time.time() - t
. No último, decorrido será negativo. Eu sugeri essa mudança como uma edição.elapsed = time.time() - t
é a forma que sempre produz um valor positivo.Eu tive a mesma pergunta quando migrei para python do Matlab. Com a ajuda deste tópico, fui capaz de construir um análogo exato do Matlab
tic()
etoc()
funções. Basta inserir o código a seguir na parte superior do seu script.É isso aí! Agora estamos prontos para usar totalmente
tic()
etoc()
exatamente como no Matlab. Por exemploNa verdade, isso é mais versátil do que as funções integradas do Matlab. Aqui, você pode criar outra instância do
TicTocGenerator
para controlar várias operações ou apenas para cronometrar as coisas de forma diferente. Por exemplo, enquanto cronometramos um script, agora podemos cronometrar cada parte do script separadamente, bem como o script inteiro. (Vou dar um exemplo concreto)Agora você deve ser capaz de cronometrar duas coisas distintas: No exemplo a seguir, cronometramos o script total e partes de um script separadamente.
Na verdade, você nem precisa usar
tic()
cada vez. Se você tem uma série de comandos que deseja cronometrar, pode escreverEspero que isso seja útil.
fonte
O melhor análogo absoluto de tic e toc seria simplesmente defini-los em python.
Então você pode usá-los como:
fonte
tic
etoc
, que o Matlab suporta. Um pouco mais de sofisticação seria necessário.import time
externa de ambas as funções, já que pode levar algum tempo.tic
empurrar etoc
sair dela.timeit.default_timer()
é melhor do quetime.time()
porquetime.clock()
pode ser mais apropriado dependendo do sistema operacionalNormalmente, IPython de
%time
,%timeit
,%prun
e%lprun
(caso tenhaline_profiler
instalado) satisfazer as minhas necessidades de perfis muito bem. No entanto, um caso de uso paratic-toc
funcionalidade semelhante surgiu quando tentei traçar o perfil de cálculos que eram dirigidos interativamente, ou seja, pelo movimento do mouse do usuário em uma GUI. Achei que enviar spam paratic
s etoc
s nas fontes enquanto testava interativamente seria a maneira mais rápida de revelar os gargalos. Fui com aTimer
aula de Eli Bendersky , mas não fiquei muito feliz, pois me obrigou a alterar a indentação do meu código, o que pode ser inconveniente em alguns editores e confunde o sistema de controle de versão. Além disso, pode haver a necessidade de medir o tempo entre pontos em diferentes funções, o que não funcionaria com owith
declaração. Depois de tentar muita inteligência Python, aqui está a solução simples que achei que funcionou melhor:Uma vez que isso funciona empurrando os tempos iniciais em uma pilha, funcionará corretamente para vários níveis de
tic
s etoc
s. Ele também permite alterar a string de formato datoc
instrução para exibir informações adicionais, o que eu gostei naTimer
aula de Eli .Por algum motivo, fiquei preocupado com a sobrecarga de uma implementação Python pura, então testei um módulo de extensão C também:
Isso é para MacOSX e omiti o código para verificar se
lvl
está fora dos limites por questão de brevidade. Emboratictoc.res()
produza uma resolução de cerca de 50 nanossegundos em meu sistema, descobri que o jitter de medir qualquer instrução Python está facilmente na faixa de microssegundos (e muito mais quando usado no IPython). Nesse ponto, a sobrecarga da implementação Python torna-se insignificante, de modo que pode ser usada com a mesma confiança da implementação C.Descobri que a utilidade da
tic-toc
abordagem -é praticamente limitada a blocos de código que levam mais de 10 microssegundos para serem executados. Abaixo disso, estratégias de média como emtimeit
são necessárias para obter uma medição fiel.fonte
Você pode usar
tic
etoc
dettictoc
. Instale comE basta importá-los em seu script da seguinte forma
fonte
Acabei de criar um módulo [tictoc.py] para obter tic tocs aninhados, que é o que o Matlab faz.
E funciona assim:
Espero que ajude.
fonte
Dê uma olhada no
timeit
módulo. Não é realmente equivalente, mas se o código que você deseja cronometrar estiver dentro de uma função, você pode usá-lo facilmente.fonte
timeit
é melhor para benchmarks. Não precisa ser uma única função, você pode passar instruções abritariamente complexas.No código:
Isenção de responsabilidade: sou o autor desta biblioteca.
fonte
Isso também pode ser feito usando um invólucro. Maneira muito geral de marcar o tempo.
O wrapper neste código de exemplo envolve qualquer função e imprime a quantidade de tempo necessária para executar a função:
fonte
Mudei um pouco a resposta de @Eli Bendersky para usar o ctor
__init__()
e o dtor__del__()
para fazer o tempo, para que possa ser usado de maneira mais conveniente sem recuar o código original:Para usar, basta colocar Timer ("blahblah") no início de algum escopo local. O tempo decorrido será impresso no final do escopo:
Ele imprime:
fonte
timer
não é excluída após a última chamada, se qualquer outro código segue após ofor
loop. Para obter o último valor do temporizador, deve-se excluir ou sobrescrever otimer
after thefor
loop, por exemplo, viatimer = None
.Atualizando a resposta de Eli para Python 3:
Assim como o de Eli, ele pode ser usado como um gerenciador de contexto:
Resultado:
Também o atualizei para imprimir as unidades de tempo relatadas (segundos) e cortar o número de dígitos conforme sugerido por Can, e com a opção de também anexar a um arquivo de log. Você deve importar data e hora para usar o recurso de registro:
fonte
Com base nas respostas de Stefan e antonimmo, acabei colocando
em um
utils.py
módulo, e eu o uso com umDeste jeito
tic()
,toc()
e ninho-los como em Matlabtic(1)
,toc(1)
outic('very-important-block')
,toc('very-important-block')
e temporizadores com nomes diferentes não irá interferir(aqui toc não imprime o tempo decorrido, mas o retorna.)
fonte