program - Medición del tiempo transcurrido en Python
timeit python (6)
Las funciones de ejemplo que indica en su edición son dos cosas completamente diferentes:
- Linux times() devuelve tiempos de proceso en milisegundos de CPU. El equivalente de Python es time.clock () o
os.times()
. - Windows GetTickCount64() devuelve el tiempo de actividad del sistema.
Aunque dos funciones diferentes, ambas (potencialmente) podrían usarse para revelar un reloj del sistema que tuvo un "eructo" con estos métodos:
Primero:
Puede tomar tanto una hora del sistema con time.time()
como una hora de CPU con time.clock()
. Como el tiempo del reloj de pared SIEMPRE será mayor o igual que el tiempo de la CPU, descarte cualquier medida en la que el intervalo entre las dos lecturas time.time()
sea menor que las time.clock()
emparejadas de time.clock()
check.
Ejemplo:
t1=time.time()
t1check=time.clock()
# your timed event...
t2=time.time()
t2check=time.clock()
if t2-t1 < t2check - t1check:
print "Things are rotten in Denmark"
# discard that sample
else:
# do what you do with t2 - t1...
Segundo:
Obtener tiempo de actividad del sistema también es prometedor si le preocupa el reloj del sistema, ya que un reinicio del usuario no restablece el conteo de tics de tiempo de actividad en la mayoría de los casos. (que yo sepa ...)
Ahora la pregunta más difícil: obtener el tiempo de actividad del sistema de una manera independiente de la plataforma, especialmente sin generar un nuevo caparazón, con la precisión del segundo segundo. Hmmm ...
Probablemente la mejor apuesta es psutil . Al navegar por la fuente , usan uptime = GetTickCount() / 1000.00f;
para Windows y sysctl "kern.boottime"
para BSD / OS X, etc. Lamentablemente, se trata de resoluciones de 1 segundo.
¿Existe una forma / módulo simple para medir correctamente el tiempo transcurrido en Python? Sé que puedo simplemente llamar a time.time()
dos veces y tomar la diferencia, pero eso arrojará resultados incorrectos si se cambia la hora del sistema. Por supuesto, eso no sucede muy a menudo, pero indica que estoy midiendo lo incorrecto.
Usar time.time()
para medir duraciones es increíblemente indirecto cuando lo piensas. Usted toma la diferencia de dos mediciones de tiempo absoluto que a su vez están construidas a partir de medidas de duración (realizadas por temporizadores) y tiempos absolutos conocidos (establecidos manualmente o mediante ntp), que no le interesan en absoluto.
Entonces, ¿hay alguna forma de consultar este "tiempo del temporizador" directamente? Me imagino que se puede representar como un valor de milisegundos o microsegundos que no tiene una representación absoluta significativa (y por lo tanto no necesita ajustarse con la hora del sistema). Al mirar un poco, parece que esto es exactamente lo que hace System.nanoTime()
en Java, pero no encontré una función Python correspondiente, aunque debería ser (hardware-technical) más fácil de proporcionar que time.time()
.
Editar: para evitar confusiones y abordar las respuestas a continuación: No se trata de cambios en el horario de verano, tampoco quiero tiempo de CPU, quiero tiempo físico transcurrido. No necesita ser muy refinado, ni siquiera particularmente preciso. Simplemente no debería darme duraciones negativas, o duraciones que están apagadas por varios órdenes de magnitud (por encima de la granularidad), solo porque alguien decidió configurar el reloj del sistema a un valor diferente. Esto es lo que dicen los Python sobre ''time.time ()'':
Esto es exactamente lo que quiero evitar, ya que puede llevar a cosas extrañas, como valores negativos en los cálculos de tiempo. Puedo solucionar esto en este momento, pero creo que es una buena idea aprender a usar las soluciones adecuadas donde sea posible, ya que los kludges volverán a morderlo algún día.
Edit2: Algunas investigaciones muestran que puede obtener una medición independiente del tiempo del sistema como la que quiero en Windows usando GetTickCount64 (), en Linux puede obtenerla en el valor de retorno de times (). Sin embargo, todavía no puedo encontrar un módulo que proporcione esta funcionalidad en Python.
Lo que parece que estás buscando es un temporizador monótono . Una referencia de tiempo monotónica no salta ni retrocede.
Ha habido varios intentos de implementar un reloj monotómico multiplataforma para Python basado en la referencia del sistema operativo. (Windows, POSIX y BSD son bastante diferentes) Consulte las discusiones y algunos de los intentos en tiempo monótono en esta publicación SO .
Sobre todo, puedes usar os.times ():
os.times ()
Devuelve una tupla de 5 números de punto flotante que indica el tiempo acumulado (procesador u otro) en segundos. Los elementos son: tiempo de usuario, hora del sistema, hora del usuario de los niños, hora del sistema de los niños y tiempo real transcurrido desde un punto fijo en el pasado, en ese orden. Consulte la página del manual de Unix veces (2) o la documentación correspondiente de la API de Windows Platform. En Windows, solo se rellenan los dos primeros elementos, los otros son cero.
Disponibilidad: Unix, Windows
Pero eso no completa el tiempo real necesario transcurrido (la quinta tupla) en Windows.
Si necesita soporte de Windows, considere ctypes
y puede llamar a GetTickCount64 () directamente, como se ha hecho en esta receta .
Para medir el tiempo de CPU transcurrido, mira time.clock() . Este es el equivalente del campo de tiempo de usuario times() de Linux.
Para la evaluación comparativa, use timeit .
El módulo datetime , que es parte de Python 2.3+ , también tiene un tiempo de microsegundo si es compatible con la plataforma.
Ejemplo:
>>> import datetime as dt
>>> n1=dt.datetime.now()
>>> n2=dt.datetime.now()
>>> (n2-n1).microseconds
678521
>>> (n2.microsecond-n1.microsecond)/1e6
0.678521
ie, it took me .678521 seconds to type the second n2= line -- slow
>>> n1.resolution
datetime.timedelta(0, 0, 1)
1/1e6 resolution is claimed.
Si le preocupan los cambios de tiempo del sistema (de DS -> ST) simplemente verifique el objeto devuelto por fecha y hora. Presumiblemente, la hora del sistema podría tener un pequeño ajuste a partir de un ajuste de referencia NTP . Esto se debe eliminar , y las correcciones se aplican gradualmente , pero los tiempos de sincronización ntp pueden tener un efecto con referencias de tiempo muy pequeñas (milisegundos o microsegundos).
También puede hacer referencia a la función C de Alex Martelli si quiere algo de esa resolución. No iría demasiado lejos para reinventar la rueda. El tiempo preciso es básico y la mayoría de los SO modernos hacen un trabajo bastante bueno.
Editar
En función de sus aclaraciones, parece que necesita una verificación lateral simple si el reloj del sistema ha cambiado. Simplemente compare con un servidor ntp local amigable:
import socket
import struct
import time
ntp="pool.ntp.org" # or whatever ntp server you have handy
client = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
data = ''/x1b'' + 47 * ''/0''
client.sendto( data, ( ntp, 123 ))
data, address = client.recvfrom( 1024 )
if data:
print ''Response received from:'', address
t = struct.unpack( ''!12I'', data )[10]
t -= 2208988800L #seconds since Epoch
print ''/tTime=%s'' % time.ctime(t)
NTP tiene una precisión de milisegundos a través de Internet y tiene una resolución de representación de resolución de 2-32 segundos (233 picosegundos). Debería ser lo suficientemente bueno?
Tenga en cuenta que la estructura de datos de NTP de 64 bits se desbordará en 2036 y cada 136 años a partir de entonces ; si realmente desea una solución sólida, compruebe mejor el desbordamiento ...
Python 3.3 agregó un temporizador monotónico en la biblioteca estándar, que hace exactamente lo que estaba buscando. Gracias a Paddy3118 por señalar esto en "¿Cómo obtengo duraciones de tiempo monótonas en python?" .
>>> import datetime
>>> t1=datetime.datetime.utcnow()
>>> t2=datetime.datetime.utcnow()
>>> t2-t1
datetime.timedelta(0, 8, 600000)
El uso de UTC evita esos períodos embarazosos cuando el reloj cambia debido al horario de verano.
En cuanto a utilizar un método alternativo en lugar de restar dos relojes, tenga en cuenta que el sistema operativo realmente contiene un reloj que se inicializa desde un reloj de hardware en la PC. Las implementaciones modernas del sistema operativo también mantendrán ese reloj sincronizado con alguna fuente oficial para que no se desplace. Esto es mucho más preciso que cualquier temporizador de intervalo que la PC pueda estar ejecutando.
from datetime import datetime
start = datetime.now()
print ''hello''
end = datetime.now()
delta = end-start
print type(delta)
<type ''datetime.timedelta''>
import datetime
help(datetime.timedelta)
...elapsed seconds and microseconds...