Posso dargli numeri in virgola mobile, come
time.sleep(0.5)
ma quanto è preciso? Se lo do
time.sleep(0.05)
dormirà davvero per circa 50 ms?
Risposte:
La precisione della funzione time.sleep dipende dalla precisione del sonno del sistema operativo sottostante. Per i sistemi operativi non in tempo reale come un Windows stock, l'intervallo più piccolo per cui puoi dormire è di circa 10-13 ms. Ho visto sleep accurati entro diversi millisecondi da quel tempo quando sono superiori al minimo di 10-13 ms.
Aggiornamento: come menzionato nei documenti citati di seguito, è comune fare il sonno in un ciclo che si assicurerà di tornare a dormire se ti sveglia presto.
Dovrei anche menzionare che se stai usando Ubuntu puoi provare uno pseudo kernel in tempo reale (con il set di patch RT_PREEMPT) installando il pacchetto del kernel rt (almeno in Ubuntu 10.04 LTS).
EDIT: I kernel Linux non in tempo reale di correzione hanno un intervallo di sospensione minimo molto più vicino a 1 ms quindi 10 ms, ma varia in modo non deterministico.
sleep()
dai documenti "il tempo di sospensione potrebbe essere più lungo di quanto richiesto da una quantità arbitraria a causa della pianificazione di altra attività nel sistema ".
Le persone hanno ragione sulle differenze tra sistemi operativi e kernel, ma non vedo alcuna granularità in Ubuntu e vedo una granularità di 1 ms in MS7. Suggerendo un'implementazione diversa di time.sleep, non solo una diversa frequenza di tick. Un'ispezione più attenta suggerisce una granularità di 1μs in Ubuntu, a proposito, ma ciò è dovuto alla funzione time.time che uso per misurare la precisione.
Dalla documentazione :
D'altra parte, la precisione di
time()
edsleep()
è migliore dei loro equivalenti Unix: i tempi sono espressi come numeri in virgola mobile,time()
restituisce il tempo più accurato disponibile (utilizzando Unixgettimeofday
dove disponibile) esleep()
accetterà un tempo con una frazione diversa da zero (select
viene utilizzato Unix per implementarlo, se disponibile).
E più specificamente rispetto a sleep()
:
Sospendi l'esecuzione per il numero di secondi specificato. L'argomento può essere un numero in virgola mobile per indicare un tempo di sospensione più preciso. Il tempo di sospensione effettivo può essere inferiore a quello richiesto perché qualsiasi segnale catturato terminerà la
sleep()
successiva esecuzione della routine di cattura di quel segnale. Inoltre, il tempo di sospensione può essere più lungo di quanto richiesto da un importo arbitrario a causa della programmazione di altre attività nel sistema.
Ecco il mio seguito alla risposta di Wilbert: lo stesso per Mac OS X Yosemite, dal momento che non è stato ancora menzionato molto.
Sembra che la maggior parte delle volte dorma circa 1,25 volte il tempo richiesto e talvolta dorma tra 1 e 1,25 volte il tempo richiesto. Non dorme quasi mai (~ due volte su 1000 campioni) per un tempo significativamente maggiore di 1,25 volte il tempo richiesto.
Inoltre (non mostrato esplicitamente) la relazione 1,25 sembra reggere abbastanza bene fino a quando non si scende al di sotto di circa 0,2 ms, dopodiché inizia a diventare un po 'sfocata. Inoltre, il tempo effettivo sembra stabilizzarsi a circa 5 ms in più rispetto a quanto richiesto dopo che la quantità di tempo richiesta supera i 20 ms.
Ancora una volta, sembra essere un'implementazione completamente diversa sleep()
in OS X rispetto a Windows o qualsiasi altro kernel Linux che Wilbert stesse usando.
Perché non scopri:
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
Per la cronaca, ottengo circa 0,1 ms di errore sul mio HTPC e 2 ms sul mio laptop, entrambe le macchine Linux.
Una piccola correzione, molte persone affermano che il sonno può essere interrotto presto da un segnale. Nei documenti 3.6 si dice,
Modificato nella versione 3.5: la funzione ora dorme almeno secondi anche se il sonno viene interrotto da un segnale, tranne se il gestore del segnale solleva un'eccezione (vedere PEP 475 per la motivazione).
Non puoi davvero garantire nulla su sleep (), tranne che farà del suo meglio per dormire finché glielo dici (i segnali possono uccidere il tuo sonno prima che il tempo sia scaduto, e molte più cose possono farlo funzionare lungo).
Sicuramente il minimo che puoi ottenere su un sistema operativo desktop standard sarà di circa 16 ms (granularità del timer più tempo per il cambio di contesto), ma è probabile che la deviazione% dall'argomento fornito sarà significativa quando stai provando dormire per 10 secondi di millisecondi.
Segnali, altri thread che mantengono il GIL, divertimento nella pianificazione del kernel, aumento della velocità del processore, ecc.
Testato di recente su Python 3.7 su Windows 10. La precisione era di circa 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()
Non utilizzare una variabile per passare l'argomento di sleep (), devi inserire il calcolo direttamente in sleep ()
E il ritorno del mio terminale
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 ─────────────────────