Puedo darle números de punto flotante, como
time.sleep(0.5)
pero ¿qué tan exacto es? Si lo doy
time.sleep(0.05)
¿Realmente dormirá unos 50 ms?
Respuestas:
La precisión de la función time.sleep depende de la precisión del sueño del sistema operativo subyacente. Para sistemas operativos que no son en tiempo real, como Windows estándar, el intervalo más pequeño que puede dormir es de aproximadamente 10-13 ms. He visto dormidos precisos dentro de varios milisegundos de ese tiempo cuando está por encima del mínimo de 10-13 ms.
Actualización: como se menciona en los documentos que se citan a continuación, es común dormir en un bucle que se asegurará de volver a dormir si lo despierta temprano.
También debo mencionar que si está ejecutando Ubuntu, puede probar un kernel pseudo en tiempo real (con el conjunto de parches RT_PREEMPT) instalando el paquete rt kernel (al menos en Ubuntu 10.04 LTS).
EDITAR: Los kernels de corrección de Linux en tiempo no real tienen un intervalo de suspensión mínimo mucho más cercano a 1 ms que a 10 ms, pero varía de manera no determinista.
sleep()
de los documentos "el tiempo de suspensión puede ser más largo de lo solicitado por una cantidad arbitraria debido a la programación de otra actividad en el sistema ".
La gente tiene razón sobre las diferencias entre los sistemas operativos y los kernels, pero no veo ninguna granularidad en Ubuntu y veo una granularidad de 1 ms en MS7. Sugerir una implementación diferente de time.sleep, no solo una tasa de tick diferente. Una inspección más cercana sugiere una granularidad de 1μs en Ubuntu por cierto, pero eso se debe a la función time.time que utilizo para medir la precisión.
De la documentación :
Por otro lado, la precisión de
time()
ysleep()
es mejor que sus equivalentes de Unix: los tiempos se expresan como números de punto flotante,time()
devuelve el tiempo más exacto disponible (usando Unixgettimeofday
donde esté disponible) ysleep()
aceptará un tiempo con una fracción distinta de cero (select
se usa Unix para implementar esto, donde esté disponible).
Y más específicamente wrt sleep()
:
Suspender la ejecución durante el número de segundos especificado. El argumento puede ser un número de coma flotante para indicar un tiempo de reposo más preciso. El tiempo de suspensión real puede ser menor que el solicitado porque cualquier señal capturada terminará la
sleep()
siguiente ejecución de la rutina de captura de esa señal. Además, el tiempo de suspensión puede ser más largo de lo solicitado por una cantidad arbitraria debido a la programación de otra actividad en el sistema.
Aquí está mi seguimiento de la respuesta de Wilbert: lo mismo para Mac OS X Yosemite, ya que aún no se ha mencionado mucho.
Parece que la mayor parte del tiempo duerme aproximadamente 1,25 veces el tiempo que solicitas y, a veces, duerme entre 1 y 1,25 veces el tiempo que solicitas. Casi nunca (~ dos veces de 1000 muestras) duerme significativamente más de 1,25 veces el tiempo que solicitas.
Además (no se muestra explícitamente) la relación de 1,25 parece mantenerse bastante bien hasta que llega por debajo de 0,2 ms, después de lo cual comienza a volverse un poco borrosa. Además, el tiempo real parece establecerse en aproximadamente 5 ms más de lo solicitado después de que la cantidad de tiempo solicitada supera los 20 ms.
Nuevamente, parece ser una implementación completamente diferente sleep()
en OS X que en Windows o cualquier kernal de Linux que Wilbert estuviera usando.
¿Por qué no lo averigua?
from datetime import datetime
import time
def check_sleep(amount):
start = datetime.now()
time.sleep(amount)
end = datetime.now()
delta = end-start
return delta.seconds + delta.microseconds/1000000.
error = sum(abs(check_sleep(0.050)-0.050) for i in xrange(100))*10
print "Average error is %0.2fms" % error
Para el registro, obtengo un error de alrededor de 0.1ms en mi HTPC y 2ms en mi computadora portátil, ambas máquinas Linux.
Una pequeña corrección, varias personas mencionan que el sueño puede interrumpirse temprano con una señal. En los documentos 3.6 dice:
Modificado en la versión 3.5: la función ahora duerme al menos segundos incluso si el sueño es interrumpido por una señal, excepto si el manejador de señales genera una excepción (ver PEP 475 para la justificación).
Realmente no puede garantizar nada sobre el sueño (), excepto que al menos hará el mejor esfuerzo para dormir siempre que lo haya dicho (las señales pueden matar su sueño antes de que se acabe el tiempo, y muchas más cosas pueden hacer que funcione largo).
Seguro que el mínimo que puede obtener en un sistema operativo de escritorio estándar será de alrededor de 16 ms (granularidad del temporizador más tiempo para cambiar de contexto), pero es probable que el% de desviación del argumento proporcionado sea significativo cuando lo intente dormir durante 10 segundos de milisegundos.
Las señales, otros subprocesos que sostienen el GIL, la diversión de programación del kernel, el paso de la velocidad del procesador, etc. pueden causar estragos en la duración de su subproceso / proceso.
Probado esto recientemente en Python 3.7 en Windows 10. La precisión fue de alrededor de 1 ms.
def start(self):
sec_arg = 10.0
cptr = 0
time_start = time.time()
time_init = time.time()
while True:
cptr += 1
time_start = time.time()
time.sleep(((time_init + (sec_arg * cptr)) - time_start ))
# AND YOUR CODE .......
t00 = threading.Thread(name='thread_request', target=self.send_request, args=([]))
t00.start()
No use una variable para pasar el argumento de sleep (), debe insertar el cálculo directamente en sleep ()
Y el regreso de mi terminal
1 ───── 17: 20: 16.891 ───────────────────
2 ───── 17: 20: 18.891 ───────────────────
3 ───── 17: 20: 20.891 ───────────────────
4 ───── 17: 20: 22.891 ───────────────────
5 ───── 17: 20: 24.891 ───────────────────
....
689 ─── 17: 43: 12.891 ────────────────────
690 ─── 17: 43: 14.890 ────────────────────
691 ─── 17: 43: 16.891 ────────────────────
692 ─── 17: 43: 18.890 ────────────────────
693 ─── 17: 43: 20.891 ────────────────────
...
727 ─── 17: 44: 28.891 ────────────────────
728 ─── 17: 44: 30.891 ────────────────────
729 ─── 17: 44: 32.891 ────────────────────
730 ─── 17: 44: 34.890 ────────────────────
731 ─── 17: 44: 36.891 ────────────────────