Si realmente desea el equivalente directo, simplemente llame tic = time.time()y toc = time.time(), print toc-tic, 'sec Elapsed'como la gente ha dicho a continuación, timeites más robusto.
Joe Kington
Parece que obtengo mejores resultados usando el enfoque de @ JoeKington junto con timeit.default_timer (), como este, por ejemplo:, tic = timeit.default_timer(); (U,S,V) = np.linalg.svd(A); toc = timeit.default_timer()entonces print toc-tic.
littleO
1
La biblioteca pytictoc parece más conveniente, la sintaxis es incluso un poco más ordenada que la de ttictoc a continuación. pypi.org/project/pytictoc
FlorianH
Respuestas:
172
Aparte de lo timeitque ThiefMaster mencionó, una forma sencilla de hacerlo es simplemente (después de importar time):
t = time.time()# do stuff
elapsed = time.time()- t
@eat: Respetuosamente no estoy de acuerdo. La gente ha estado usando el timecomando Unix para medir los tiempos de ejecución de los programas desde siempre, y este método replica esto dentro del código Python. No veo nada malo en ello, siempre que sea la herramienta adecuada para el trabajo. timeitno siempre es eso, y un generador de perfiles es una solución mucho más pesada para la mayoría de las necesidades
Eli Bendersky
4
Para la última línea, sugeriría print 'Elapsed: %.2f seconds % (time.time() - self.tstart)'. Es difícil de entender sin% .2f. Gracias por la gran idea.
Can Kavaklıoğlu
4
Esto parece muy conveniente a primera vista, pero en la práctica requiere que uno haga una sangría en el bloque de código que desea cronometrar, lo que puede ser bastante inconveniente dependiendo de la longitud del bloque de código y del editor elegido. Sigue siendo una solución elegante, que se comporta correctamente en el caso de uso anidado.
Stefan
1
Creo que quieres elapsed = t - time.time(), en lugar de elapsed = time.time() - t. En este último transcurrido será negativo. Sugerí este cambio como una edición.
rysqui
3
@rysqui - ¿No es la hora actual siempre un número mayor que la hora anterior ? Creo que elapsed = time.time() - tes la forma que siempre da un valor positivo.
Scott Smith
32
Tuve la misma pregunta cuando migré a Python desde Matlab. Con la ayuda de este hilo pude construir un análogo exacto de Matlab tic()y toc()funciones. Simplemente inserte el siguiente código en la parte superior de su secuencia de comandos.
import time
defTicTocGenerator():# 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)
¡Eso es! Ahora estamos listos para usar completamente tic()y toc()al igual que en Matlab. Por ejemplo
En realidad, esto es más versátil que las funciones integradas de Matlab. Aquí, puede crear otra instancia de TicTocGeneratorpara realizar un seguimiento de múltiples operaciones, o simplemente para cronometrar las cosas de manera diferente. Por ejemplo, mientras cronometramos un guión, ahora podemos cronometrar cada parte del guión por separado, así como todo el guión. (Daré un ejemplo 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)
Ahora debería poder cronometrar dos cosas distintas: en el siguiente ejemplo, cronometramos el guión total y partes de un guión por separado.
La mejor analogía absoluta de tic y toc sería simplemente definirlos en 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"
Esto no se comportará correctamente en el caso del uso anidado de ticy toc, que Matlab admite. Se necesitaría un poco más de sofisticación.
Stefan
2
Implementé funciones similares en mi propio código cuando necesitaba una sincronización básica. Sin embargo, eliminaría el import timeexterior de ambas funciones, ya que potencialmente puede llevar bastante tiempo.
Bas Swinckels
Si insiste en usar esta técnica y la necesita para manejar tic / toc anidado, haga una lista global y déjela ticpresionar y salir tocde ella.
Ahmed Fasih
1
También leí en otra parte que timeit.default_timer()es mejor que time.time()porque time.clock()podría ser más apropiado según el sistema operativo
Miguel
@AhmedFasih Eso es lo que hace mi respuesta, aunque se podrían mejorar más cosas.
antonimmo
15
Por lo general, IPython de %time, %timeit, %pruny %lprun(si se ha line_profilerinstalado) satisfacer mis necesidades de perfiles bastante bien. Sin embargo, tic-tocsurgió un caso de uso para una funcionalidad similar a la de cuando traté de perfilar cálculos que eran impulsados interactivamente, es decir, por el movimiento del mouse del usuario en una GUI. Me sentí como el correo basura tics y tocs en las fuentes mientras que las pruebas de forma interactiva sería la forma más rápida para revelar los cuellos de botella. Fui con la Timerclase de Eli Bendersky , pero no estaba del todo contento, ya que requería que cambiara la sangría de mi código, lo que puede ser inconveniente en algunos editores y confunde el sistema de control de versiones. Además, puede ser necesario medir el tiempo entre puntos en diferentes funciones, lo que no funcionaría con elwithdeclaración. Después de probar mucha inteligencia de Python, aquí está la solución simple que encontré que funcionaba mejor:
from time import time
_tstart_stack =[]def tic():
_tstart_stack.append(time())def toc(fmt="Elapsed: %s s"):print fmt %(time()- _tstart_stack.pop())
Dado que esto funciona presionando las horas de inicio en una pila, funcionará correctamente para múltiples niveles de ticsy tocs. También permite cambiar la cadena de formato de la tocdeclaración para mostrar información adicional, que me gustó de la Timerclase de Eli .
Por alguna razón, me preocupó la sobrecarga de una implementación de Python pura, así que también probé un módulo de extensión de C:
Esto es para MacOSX, y he omitido el código para verificar si lvlestá fuera de los límites por brevedad. Si bien tictoc.res()produce una resolución de aproximadamente 50 nanosegundos en mi sistema, descubrí que el jitter de medir cualquier declaración de Python está fácilmente en el rango de microsegundos (y mucho más cuando se usa desde IPython). En este punto, la sobrecarga de la implementación de Python se vuelve insignificante, por lo que se puede usar con la misma confianza que la implementación de C.
Descubrí que la utilidad del tic-tocenfoque-está prácticamente limitada a bloques de código que tardan más de 10 microsegundos en ejecutarse. Por debajo de eso, timeitse requieren estrategias de promediado como en para obtener una medición fiel.
Acabo de crear un módulo [tictoc.py] para lograr tic tocs anidados, que es lo que hace Matlab.
from time import time
tics =[]def tic():
tics.append(time())def toc():if len(tics)==0:returnNoneelse:return time()-tics.pop()
Y funciona de esta manera:
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()
Debo advertirle que esto podría no comportarse como se desea cuando se usa simultáneamente por más de 1 módulo, ya que los módulos (AFAIK) se comportan como singletons.
antonimmo
3
Eche un vistazo al timeitmódulo. No es realmente equivalente, pero si el código que desea cronometrar está dentro de una función, puede usarlo fácilmente.
Esto también se puede hacer usando una envoltura. Manera muy general de llevar el tiempo.
El contenedor en este código de ejemplo envuelve cualquier función e imprime la cantidad de tiempo necesaria para ejecutar la función:
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()
La función de envoltura, timethis, se llama decorador. Una explicación un poco más detallada, aquí: medium.com/pythonhive/…
Mircea
1
Cambié un poco la respuesta de @Eli Bendersky para usar ctor __init__()y dtor __del__()para hacer el tiempo, de modo que pueda usarse de manera más conveniente sin sangrar el código original:
Un problema con esta implementación es el hecho de que timerno se elimina después de la última llamada, si algún otro código sigue después del forciclo. Para obtener el último valor del temporizador, se debe eliminar o sobrescribir el timerdespués del forciclo, por ejemplo, a través de timer = None.
bastelflp
1
@bastelflp Me acabo de dar cuenta de que entendí mal lo que querías decir ... Ahora tu sugerencia se ha incorporado al código. Gracias.
Al igual que Eli, se puede utilizar como administrador de contexto:
import time
withTimer('Count'):for i in range(0,10_000_000):pass
Salida:
[Count]Elapsed:0.27 seconds
También lo he actualizado para imprimir las unidades de tiempo reportadas (segundos) y recortar el número de dígitos como sugiere Can, y con la opción de agregar también a un archivo de registro. Debe importar la fecha y la hora para usar la función de registro:
import time
import datetime
withTimer('Count','log.txt'):for i in range(0,10_000_000):pass
simplemente puedes usar tic(),toc() y nido de ellos como en Matlab
Como alternativa, puede nombrarlos: tic(1), toc(1)o tic('very-important-block'), toc('very-important-block')y temporizadores con diferentes nombres no interferirá
importarlos de esta manera evita interferencias entre los módulos que lo utilizan.
(aquí toc no imprime el tiempo transcurrido, pero lo devuelve).
tic = time.time()
ytoc = time.time()
,print toc-tic, 'sec Elapsed'
como la gente ha dicho a continuación,timeit
es más robusto.tic = timeit.default_timer(); (U,S,V) = np.linalg.svd(A); toc = timeit.default_timer()
entoncesprint toc-tic
.Respuestas:
Aparte de lo
timeit
que ThiefMaster mencionó, una forma sencilla de hacerlo es simplemente (después de importartime
):Tengo una clase de ayuda que me gusta usar:
Se puede utilizar como administrador de contexto:
A veces encuentro esta técnica más conveniente que
timeit
... todo depende de lo que quieras medir.fuente
time
comando Unix para medir los tiempos de ejecución de los programas desde siempre, y este método replica esto dentro del código Python. No veo nada malo en ello, siempre que sea la herramienta adecuada para el trabajo.timeit
no siempre es eso, y un generador de perfiles es una solución mucho más pesada para la mayoría de las necesidadesprint 'Elapsed: %.2f seconds % (time.time() - self.tstart)'
. Es difícil de entender sin% .2f. Gracias por la gran idea.elapsed = t - time.time()
, en lugar deelapsed = time.time() - t
. En este último transcurrido será negativo. Sugerí este cambio como una edición.elapsed = time.time() - t
es la forma que siempre da un valor positivo.Tuve la misma pregunta cuando migré a Python desde Matlab. Con la ayuda de este hilo pude construir un análogo exacto de Matlab
tic()
ytoc()
funciones. Simplemente inserte el siguiente código en la parte superior de su secuencia de comandos.¡Eso es! Ahora estamos listos para usar completamente
tic()
ytoc()
al igual que en Matlab. Por ejemploEn realidad, esto es más versátil que las funciones integradas de Matlab. Aquí, puede crear otra instancia de
TicTocGenerator
para realizar un seguimiento de múltiples operaciones, o simplemente para cronometrar las cosas de manera diferente. Por ejemplo, mientras cronometramos un guión, ahora podemos cronometrar cada parte del guión por separado, así como todo el guión. (Daré un ejemplo concreto)Ahora debería poder cronometrar dos cosas distintas: en el siguiente ejemplo, cronometramos el guión total y partes de un guión por separado.
En realidad, ni siquiera necesita usarlo
tic()
cada vez. Si tiene una serie de comandos que desea cronometrar, puede escribirEspero que esto sea útil.
fuente
La mejor analogía absoluta de tic y toc sería simplemente definirlos en python.
Entonces puedes usarlos como:
fuente
tic
ytoc
, que Matlab admite. Se necesitaría un poco más de sofisticación.import time
exterior de ambas funciones, ya que potencialmente puede llevar bastante tiempo.tic
presionar y salirtoc
de ella.timeit.default_timer()
es mejor quetime.time()
porquetime.clock()
podría ser más apropiado según el sistema operativoPor lo general, IPython de
%time
,%timeit
,%prun
y%lprun
(si se haline_profiler
instalado) satisfacer mis necesidades de perfiles bastante bien. Sin embargo,tic-toc
surgió un caso de uso para una funcionalidad similar a la de cuando traté de perfilar cálculos que eran impulsados interactivamente, es decir, por el movimiento del mouse del usuario en una GUI. Me sentí como el correo basuratic
s ytoc
s en las fuentes mientras que las pruebas de forma interactiva sería la forma más rápida para revelar los cuellos de botella. Fui con laTimer
clase de Eli Bendersky , pero no estaba del todo contento, ya que requería que cambiara la sangría de mi código, lo que puede ser inconveniente en algunos editores y confunde el sistema de control de versiones. Además, puede ser necesario medir el tiempo entre puntos en diferentes funciones, lo que no funcionaría con elwith
declaración. Después de probar mucha inteligencia de Python, aquí está la solución simple que encontré que funcionaba mejor:Dado que esto funciona presionando las horas de inicio en una pila, funcionará correctamente para múltiples niveles de
tic
sytoc
s. También permite cambiar la cadena de formato de latoc
declaración para mostrar información adicional, que me gustó de laTimer
clase de Eli .Por alguna razón, me preocupó la sobrecarga de una implementación de Python pura, así que también probé un módulo de extensión de C:
Esto es para MacOSX, y he omitido el código para verificar si
lvl
está fuera de los límites por brevedad. Si bientictoc.res()
produce una resolución de aproximadamente 50 nanosegundos en mi sistema, descubrí que el jitter de medir cualquier declaración de Python está fácilmente en el rango de microsegundos (y mucho más cuando se usa desde IPython). En este punto, la sobrecarga de la implementación de Python se vuelve insignificante, por lo que se puede usar con la misma confianza que la implementación de C.Descubrí que la utilidad del
tic-toc
enfoque-está prácticamente limitada a bloques de código que tardan más de 10 microsegundos en ejecutarse. Por debajo de eso,timeit
se requieren estrategias de promediado como en para obtener una medición fiel.fuente
Puede usar
tic
ytoc
desdettictoc
. Instalarlo conY simplemente impórtelos en su script de la siguiente manera
fuente
Acabo de crear un módulo [tictoc.py] para lograr tic tocs anidados, que es lo que hace Matlab.
Y funciona de esta manera:
Espero que ayude.
fuente
Eche un vistazo al
timeit
módulo. No es realmente equivalente, pero si el código que desea cronometrar está dentro de una función, puede usarlo fácilmente.fuente
timeit
es mejor para los puntos de referencia. Ni siquiera tiene que ser una función única, puede pasar declaraciones abritamente complejas.En el código:
Descargo de responsabilidad: soy el autor de esta biblioteca.
fuente
Esto también se puede hacer usando una envoltura. Manera muy general de llevar el tiempo.
El contenedor en este código de ejemplo envuelve cualquier función e imprime la cantidad de tiempo necesaria para ejecutar la función:
fuente
Cambié un poco la respuesta de @Eli Bendersky para usar ctor
__init__()
y dtor__del__()
para hacer el tiempo, de modo que pueda usarse de manera más conveniente sin sangrar el código original:Para usarlo, simplemente ponga Timer ("blahblah") al comienzo de algún ámbito local. El tiempo transcurrido se imprimirá al final del alcance:
Imprime:
fuente
timer
no se elimina después de la última llamada, si algún otro código sigue después delfor
ciclo. Para obtener el último valor del temporizador, se debe eliminar o sobrescribir eltimer
después delfor
ciclo, por ejemplo, a través detimer = None
.Actualizando la respuesta de Eli a Python 3:
Al igual que Eli, se puede utilizar como administrador de contexto:
Salida:
También lo he actualizado para imprimir las unidades de tiempo reportadas (segundos) y recortar el número de dígitos como sugiere Can, y con la opción de agregar también a un archivo de registro. Debe importar la fecha y la hora para usar la función de registro:
fuente
Basándome en las respuestas de Stefan y antonimmo, terminé poniendo
en un
utils.py
módulo, y lo uso con unDe esta manera
tic()
,toc()
y nido de ellos como en Matlabtic(1)
,toc(1)
otic('very-important-block')
,toc('very-important-block')
y temporizadores con diferentes nombres no interferirá(aquí toc no imprime el tiempo transcurrido, pero lo devuelve).
fuente