threading - temporizador python
Obtener marcas de temporizador en Python (6)
Solo estoy tratando de sincronizar una parte del código. El pseudocódigo se ve así:
start = get_ticks()
do_long_code()
print "It took " + (get_ticks() - start) + " seconds."
¿Cómo se ve esto en Python?
Más específicamente, ¿cómo obtengo el número de tics desde la medianoche (o, como quiera que Python organice ese tiempo)?
El módulo de tiempo en python le da acceso a la función clock (), que devuelve el tiempo en segundos como un punto flotante.
Los diferentes sistemas tendrán una precisión diferente en función de su configuración de reloj interno (tics por segundo), pero en general es al menos menos de 20 milisegundos y, en algunos casos, mejor que algunos microsegundos.
-Adán
import datetime
start = datetime.datetime.now()
do_long_code()
finish = datetime.datetime.now()
delta = finish - start
print delta.seconds
Desde la medianoche:
import datetime
midnight = datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
now = datetime.datetime.now()
delta = now - midnight
print delta.seconds
En el módulo de time
, hay dos funciones de time
: time
y clock
. time
le da time
"pared", si esto es lo que le importa.
Sin embargo, los python dicen que el clock
debería usarse para la evaluación comparativa. Tenga en cuenta que el clock
comporta diferente en sistemas separados:
- en MS Windows, usa la función Win32 QueryPerformanceCounter (), con "resolución típicamente mejor que un microsegundo". No tiene ningún significado especial, es solo un número (comienza a contar la primera vez que llama al
clock
en su proceso).
# ms windows t0= time.clock() do_something() t= time.clock() - t0 # t is wall seconds elapsed (floating point)
- en * nix, el
clock
informa el tiempo de CPU. Ahora, esto es diferente, y probablemente el valor que desee, ya que su programa casi nunca es el único proceso que solicita tiempo de CPU (incluso si no tiene otros procesos, el kernel utiliza el tiempo de CPU de vez en cuando). Por lo tanto, este número, que normalmente es más pequeño¹ que el tiempo de pared (es decir, time.time () - t0), es más significativo cuando se utiliza el código de evaluación comparativa:
# linux t0= time.clock() do_something() t= time.clock() - t0 # t is CPU seconds elapsed (floating point)
Además de todo eso, el módulo timeit tiene la clase Timer
que se supone que usa lo mejor para la evaluación comparativa de la funcionalidad disponible.
¹ a menos que el enhebrado se interponga en el camino ...
² Python ≥3.3: hay time.perf_counter()
y time.process_time()
. perf_counter
está siendo utilizado por el módulo timeit
.
Aquí hay una solución que comencé a usar recientemente:
class Timer:
def __enter__(self):
self.begin = now()
def __exit__(self, type, value, traceback):
print(format_delta(self.begin, now()))
Lo usas así (necesitas al menos Python 2.5):
with Timer():
do_long_code()
Cuando el código finaliza, el temporizador imprime automáticamente el tiempo de ejecución. ¡Dulce! Si estoy tratando de ubicar algo rápidamente en el intérprete de Python, esta es la forma más fácil de hacerlo.
Y aquí hay una implementación de ejemplo de ''ahora'' y ''formato_delta'', aunque puede usar su método preferido de tiempo y formato.
import datetime
def now():
return datetime.datetime.now()
# Prints one of the following formats*:
# 1.58 days
# 2.98 hours
# 9.28 minutes # Not actually added yet, oops.
# 5.60 seconds
# 790 milliseconds
# *Except I prefer abbreviated formats, so I print d,h,m,s, or ms.
def format_delta(start,end):
# Time in microseconds
one_day = 86400000000
one_hour = 3600000000
one_second = 1000000
one_millisecond = 1000
delta = end - start
build_time_us = delta.microseconds + delta.seconds * one_second + delta.days * one_day
days = 0
while build_time_us > one_day:
build_time_us -= one_day
days += 1
if days > 0:
time_str = "%.2fd" % ( days + build_time_us / float(one_day) )
else:
hours = 0
while build_time_us > one_hour:
build_time_us -= one_hour
hours += 1
if hours > 0:
time_str = "%.2fh" % ( hours + build_time_us / float(one_hour) )
else:
seconds = 0
while build_time_us > one_second:
build_time_us -= one_second
seconds += 1
if seconds > 0:
time_str = "%.2fs" % ( seconds + build_time_us / float(one_second) )
else:
ms = 0
while build_time_us > one_millisecond:
build_time_us -= one_millisecond
ms += 1
time_str = "%.2fms" % ( ms + build_time_us / float(one_millisecond) )
return time_str
Indíqueme si tiene un método de formato preferido o si existe una forma más fácil de hacerlo.
Si tiene muchas declaraciones que desea cronometrar, podría usar algo como esto:
class Ticker:
def __init__(self):
self.t = clock()
def __call__(self):
dt = clock() - self.t
self.t = clock()
return 1000 * dt
Entonces su código podría verse así:
tick = Ticker()
# first command
print(''first took {}ms''.format(tick())
# second group of commands
print(''second took {}ms''.format(tick())
# third group of commands
print(''third took {}ms''.format(tick())
De esta forma no es necesario escribir t = time()
antes de cada bloque y 1000 * (time() - t)
después de él, mientras se mantiene el control sobre el formateo (aunque también se puede poner fácilmente en Ticket
).
Es una ganancia mínima, pero creo que es bastante conveniente.