¿Medido el tiempo transcurrido en Python?

Lo que quiero es comenzar a contar el tiempo en algún lugar de mi código y luego obtener el tiempo pasado, para medir el tiempo que llevó ejecutar algunas funciones. Creo que estoy usando el módulo timeit mal, pero los documentos son confusos para mí.

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

Si solo desea medir el tiempo de reloj de pared transcurrido entre dos puntos, puede usar time.time() :

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

Esto da el tiempo de ejecución en segundos.

Otra opción desde 3.3 podría ser usar perf_counter o process_time , dependiendo de sus requisitos. Antes de 3.3 se recomendó usar time.clock (gracias Amber ). Sin embargo, actualmente está en desuso:

En Unix, devuelva el tiempo actual del procesador como un número de punto flotante expresado en segundos. La precisión, y de hecho la definición misma del significado de “tiempo de procesador”, depende de la función C del mismo nombre.

En Windows, esta función devuelve los segundos de reloj de pared transcurridos desde la primera llamada a esta función, como un número de punto flotante, basado en la función Win32 QueryPerformanceCounter() . La resolución suele ser mejor que un microsegundo.

En desuso desde la versión 3.3 : El comportamiento de esta función depende de la plataforma: use perf_counter() o process_time() lugar , según sus requisitos, para tener un comportamiento bien definido.

Utilice timeit.default_timer lugar de timeit.timeit . El primero proporciona automáticamente el mejor reloj disponible en su plataforma y versión de Python:

 from timeit import default_timer as timer start = timer() # ... end = timer() print(end - start) # Time in seconds, eg 5.38091952400282 

timeit.default_timer se asigna a time.time () o time.clock () según el sistema operativo. En Python 3.3+, default_timer es time.perf_counter () en todas las plataformas. Ver Python – time.clock () vs. time.time () – ¿exactitud?

Ver también:

  • Optimizando codigo
  • Cómo optimizar la velocidad.

Sólo Python 3:

Dado que time.clock () está en desuso a partir de Python 3.3 , deseará usar time.perf_counter() para la temporización de todo el sistema, o time.process_time() para la temporización de todo el proceso, de la misma manera que solía usar el time.clock() :

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

La nueva función process_time no incluirá el tiempo transcurrido durante la suspensión.

Dada una función que te gustaría cronometrar,

test.py:

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

la forma más fácil de usar timeit es llamarlo desde la línea de comandos:

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

No intente usar time.time o time.clock (ingenuamente) para comparar la velocidad de las funciones. Pueden dar resultados engañosos .

PD. No coloque declaraciones impresas en una función que desee progtwigr; De lo contrario, el tiempo medido dependerá de la velocidad del terminal .

Es divertido hacer esto con un administrador de contexto que recuerda automáticamente la hora de inicio al ingresar a un bloque with , luego congela la hora de finalización en la salida del bloque. Con un pequeño truco, incluso puede obtener un recuento de tiempo transcurrido dentro del bloque desde la misma función de administrador de contexto.

La biblioteca central no tiene esto (pero probablemente debería). Una vez en su lugar, puedes hacer cosas 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() ) 

Aquí está el código de contextmanager suficiente para hacer el truco:

 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 

Y algún código demo ejecutable:

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

Tenga en cuenta que al diseñar esta función, el valor de retorno de elapsed() se congela en la salida del bloque, y las llamadas posteriores devuelven la misma duración (de aproximadamente 6 segundos en este ejemplo de juguete).

Prefiero esto. timeit doc es demasiado 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)) 

Tenga en cuenta que aquí no hay ningún formato, solo escribí hh:mm:ss en la impresión para que se pueda interpretar time_elapsed

El uso de time.time para medir la ejecución le brinda el tiempo total de ejecución de sus comandos, incluido el tiempo de ejecución empleado por otros procesos en su computadora. Es el momento en que el usuario se da cuenta, pero no es bueno si desea comparar diferentes fragmentos de código / algoritmos / funciones / …

Más información sobre timeit :

  • Usando el módulo timeit
  • timeit – cronometra la ejecución de pequeños bits de código Python

Si desea una visión más profunda de los perfiles:

Actualización : usé http://pythonhosted.org/line_profiler/ mucho durante el último año y lo encuentro muy útil y recomiendo usarlo en lugar del módulo de perfil de Pythons.

Aquí hay una pequeña clase de temporizador que devuelve la cadena “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 

Los módulos Python cProfile y pstats ofrecen una gran compatibilidad para medir el tiempo transcurrido en ciertas funciones sin tener que agregar ningún código alrededor de las funciones existentes.

Por ejemplo, si tiene un script de 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 ejecutar el generador de perfiles y generar estadísticas para el archivo, simplemente puede ejecutar:

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

Lo que está haciendo es usar el módulo cProfile para perfilar todas las funciones en timeFunctions.py y recostackr las estadísticas en el archivo timeStats.profile. Tenga en cuenta que no tuvimos que agregar ningún código al módulo existente (timeFunctions.py) y esto se puede hacer con cualquier módulo.

Una vez que tenga el archivo de estadísticas, puede ejecutar el módulo pstats de la siguiente manera:

 python -m pstats timeStats.profile 

Esto ejecuta el navegador de estadísticas interactivo que te brinda una gran funcionalidad. Para su caso de uso particular, solo puede verificar las estadísticas de su función. En nuestro ejemplo, la comprobación de estadísticas para ambas funciones nos muestra lo siguiente:

 Welcome to the profile statistics browser. timeStats.profile% stats hello  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  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) 

El ejemplo ficticio no hace mucho, pero le da una idea de lo que se puede hacer. La mejor parte de este enfoque es que no tengo que editar ninguno de mis códigos existentes para obtener estos números y, obviamente, ayuda con los perfiles.

Aquí hay otro administrador de contexto para el código de tiempo:

Uso:

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

o, si necesitas el valor de tiempo

 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

Usa el modificador de perfiles. Da un perfil muy detallado.

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

produce 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 :1() 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) 

Lo he encontrado muy informativo.

(Solo con Ipython) puede usar % timeit para medir el tiempo de procesamiento promedio:

 def foo(): print "hello" 

y entonces:

 %timeit foo() 

el resultado es algo como:

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

en python3:

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

Elegante y corto.

Es una respuesta súper tardía, pero tal vez tenga un propósito para alguien. Esta es una forma de hacerlo que creo que es super limpia.

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

Tenga en cuenta que “imprimir” es una función en Python 3 y no en Python 2.7. Sin embargo, funciona con cualquier otra función. ¡Aclamaciones!

Una forma más de usar timeit :

 from timeit import timeit def func(): return 1 + 1 time = timeit(func, number=1) print(time) 

También podemos convertir el tiempo en tiempo legible 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') 

Aquí están mis conclusiones después de leer muchas buenas respuestas aquí, así como algunos otros artículos.

Primero, siempre desea usar timeit y no time.time (y en muchos casos, API de contador) porque

  1. timeit selecciona el mejor temporizador disponible en su sistema operativo y la versión de Python.
  2. timeit desactiva la recolección de basura, sin embargo, esto no es algo que puede o no desear.

Ahora el problema es que timeit no es tan fácil de usar porque necesita configuración y las cosas se ponen feas cuando tienes muchas importaciones. Lo ideal es que solo quieras un decorador o usarlo with locking y medición. Desafortunadamente, no hay nada integrado disponible para esto, así que creé a continuación un pequeño módulo de utilidad.

Módulo de utilidad de sincronización

 # 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 

Cómo progtwigr funciones

Ahora puedes progtwigr cualquier función simplemente poniendo un decorador delante de ella:

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

Cómo codificar los bloques de tiempo

Si desea cronometrar parte del código, simplemente póngalo dentro with bloque:

 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 

Ventajas

Hay varias versiones de media copia flotando alrededor, así que quiero señalar algunos aspectos destacados:

  1. Use el temporizador de timeit en lugar de time.time por las razones descritas anteriormente.
  2. Desactivar GC durante el tiempo.
  3. El decorador acepta funciones con parámetros con nombre o sin nombre.
  4. Posibilidad de deshabilitar la impresión en tiempo de bloque (usar with utils.MeasureBlockTime() as t y luego t.elapsed ).
  5. Posibilidad de mantener gc habilitado para la temporización de bloque.

Hice una biblioteca para esto, si quieres medir una función, puedes hacerlo así

 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

Puedes usar timeit.

Aquí hay un ejemplo sobre cómo probar naive_func que toma parámetros usando 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 

No necesita la función de envoltorio si la función no tiene ningún parámetro.

Tiempo de medición en segundos:

 from timeit import default_timer as timer from datetime import timedelta start = timer() end = timer() print(timedelta(seconds=end-start)) 

La única forma en que puedo pensar es 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 eso ayude.

Mejor uso del tiempo, simplemente: (ejecuta varias ejecuciones para el mismo comando y le proporciona los resultados).

El ejemplo se da a continuación:

 %timeit import pandas as pd 

Además de %timeit en ipython , también puede usar %%timeit para fragmentos de código de varias líneas:

 In [1]: %%timeit ...: complex_func() ...: 2 + 2 == 5 ...: ...: 1 s ± 1.93 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 

También se puede usar en el cuaderno de jupyter de la misma manera, solo coloque magic %%timeit al comienzo de la celda.