sacar - ¿Medido el tiempo transcurrido en Python?
tiempo en python (21)
Sólo Python 3:
Dado que time.clock () está en desuso a partir de Python 3.3 , deseará usar perf_counter para la temporización de todo el sistema, o 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.
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 mal el módulo timeit, pero los documentos son confusos para mí.
import timeit
start = timeit.timeit()
print "hello"
end = timeit.timeit()
print end - start
(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
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
-
timeit
selecciona el mejor temporizador disponible en su sistema operativo y la versión de Python. -
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 que uses with
bloqueo y medición. Desafortunadamente, no hay nada integrado disponible para esto, así que creé debajo del 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 programar funciones
Ahora puedes programar 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:
- Use el temporizador de timeit en lugar de time.time por las razones descritas anteriormente.
- Desactivar GC durante el tiempo.
- El decorador acepta funciones con parámetros con nombre o sin nombre.
- Posibilidad de deshabilitar la impresión en tiempo de bloque (usar
with utils.MeasureBlockTime() as t
y luegot.elapsed
). - Posibilidad de mantener gc habilitado para la temporización de bloque.
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 dabeaz.blogspot.fr/2010/02/…
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
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 comando:
% 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 programar; De lo contrario, el tiempo medido dependerá de la velocidad del terminal .
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
:
Si desea una visión más profunda de los perfiles:
- http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Profiling_Code
- ¿Cómo puedes perfilar un script de python?
Actualización : Utilicé 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.
Es divertido hacer esto con un administrador de contexto que recuerda automáticamente la hora de inicio al ingresar a un bloque with
, y 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).
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!
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)
La única manera 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.
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 utilizar el módulo cProfile para perfilar todas las funciones en timeFunctions.py y recopilar 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
<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)
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.
Mejor use timeit 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
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
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 envoltura si la función no tiene ningún parámetro.
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()
oprocess_time()
lugar , según sus requisitos, para tener un comportamiento bien definido.
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'')
Una forma más de usar timeit :
from timeit import timeit
def func():
return 1 + 1
time = timeit(func, number=1)
print(time)
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 <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)
Lo he encontrado muy informativo.
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, e.g. 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:
en python3:
from time import sleep, perf_counter as pc
t0 = pc()
sleep(1)
print(pc()-t0)
Elegante y corto.