web-dev-qa-db-fra.com

Quelle est la précision de time.sleep () de python?

Je peux lui donner des nombres en virgule flottante, tels que

time.sleep(0.5)

mais quelle est sa précision? Si je le donne

time.sleep(0.05)

va-t-il vraiment dormir environ 50 ms?

70
Claudiu

La précision de la fonction time.sleep dépend de la précision du sommeil de votre système d'exploitation sous-jacent. Pour les systèmes d’exploitation non temps réel tels que Windows standard, le plus petit intervalle pour lequel vous pouvez dormir est d’environ 10-13 ms. J'ai observé des périodes de sommeil précises en quelques millisecondes au-dessus de 10-13 ms minimum.

Mise à jour: Comme mentionné dans la documentation citée ci-dessous, il est courant de dormir en boucle, ce qui vous permettra de vous rendormir si cela vous réveille tôt.

Je devrais également mentionner que si vous utilisez Ubuntu, vous pouvez essayer un noyau pseudo-temps réel (avec le jeu de correctifs RT_PREEMPT) en installant le package de noyau rt (au moins dans Ubuntu 10.04 LTS).

EDIT: Les noyaux Linux de correction en temps non réel ont un intervalle de repos minimum beaucoup plus proche de 1 ms que 10 ms, mais il varie de manière non déterministe.

63
Joseph Lisee

Les gens ont bien raison en ce qui concerne les différences entre les systèmes d'exploitation et les noyaux, mais je ne vois aucune granularité dans Ubuntu et une granularité de 1 ms dans MS7. Suggérer une implémentation différente de time.sleep, pas simplement un taux de tick différent. Une inspection plus minutieuse suggère une granularité de 1 μs dans Ubuntu, mais cela est dû à la fonction time.time que j'utilise pour mesurer la précision .Linux and Windows typical time.sleep behaviour in Python

45
Wilbert

De la documentation :

D'autre part, la précision de time() et sleep() est supérieur à leurs équivalents Unix: times are exprimé en nombres à virgule flottante, time() renvoie l'heure la plus précise disponible (en utilisant Unix gettimeofday si disponible), et sleep() will accepter un temps avec une fraction non nulle (Unix select est utilisé pour implémenter This, le cas échéant).

Et plus spécifiquement w.r.t. sleep():

Suspendre l'exécution pour le nombre donné de secondes. L'argument peut être un nombre en virgule flottante pour indiquer un temps de sommeil plus précis. L'actuel le temps de suspension peut être inférieur à cela demandé parce que tout signal capturé mettra fin au sleep() suivant exécution de la capture de ce signal routine. En outre, le temps de suspension may être plus long que demandé par un montant arbitraire en raison de la programmation d'une autre activité dans le système.

24
Stephan202

Pourquoi ne découvres-tu pas:

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

Pour mémoire, je reçois une erreur de 0,1 ms sur mon HTPC et 2 ms sur mon ordinateur portable, les deux machines Linux.

14
Ants Aasma

Voici ma suite à la réponse de Wilbert: la même chose pour Mac OS X Yosemite, puisque cela n'a pas encore été beaucoup mentionné.Sleep behavior of Mac OS X Yosemite

Il semble que la plupart du temps, il dort environ 1,25 fois le temps que vous demandez et dort parfois entre 1 et 1,25 fois le temps que vous demandez. Il ne dort presque jamais (environ deux fois sur 1000 échantillons) plus de 1,25 fois le temps demandé. 

De plus (non montré explicitement) la relation 1.25 semble bien tenir jusqu'à ce que vous tombiez en dessous de 0,2 ms environ, après quoi elle commence à devenir un peu floue. En outre, le temps réel semble s'équilibrer d'environ 5 ms par rapport à la demande après que la durée demandée dépasse 20 ms.

Encore une fois, cela semble être une implémentation complètement différente de sleep() dans OS X par rapport à Windows ou à celui utilisé par Wilbert sous Linux.

13
Tim Supinie

Vous ne pouvez vraiment pas garantir quoi que ce soit à propos de sleep (), sauf qu'il fera au moins le meilleur effort possible pour dormir aussi longtemps que vous le lui direz (les signaux peuvent tuer votre sommeil avant qu'il ne soit trop tard et beaucoup d'autres choses peuvent le faire fonctionner longue).

Bien sûr, le minimum que vous pouvez obtenir sur un système d'exploitation de bureau standard sera d'environ 16 ms (granularité de la minuterie plus délai de commutation du contexte), mais il est probable que l'écart en% par rapport à l'argument fourni sera significatif lorsque vous essayez. dormir pendant 10s de millisecondes. 

Les signaux, les autres threads contenant le GIL, l'amusement de la planification du noyau, le pas de la vitesse du processeur, etc. peuvent tous faire des ravages avec la durée de sommeil de votre thread/processus.

2
Nick Bastin

Une petite correction, plusieurs personnes mentionnent que le sommeil peut être terminé tôt par un signal. Dans les 3.6 docs il dit,

Modifié dans la version 3.5: La fonction dort maintenant au moins secondes même si le sommeil est interrompu par un signal, sauf si le gestionnaire de signaux soulève une exception (voir PEP 475 pour la justification).

2
user405

Ceci a récemment été testé sur Python 3.7 sous Windows 10. La précision était d'environ 1 ms.

0
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()

Ne pas utiliser une variable pour passer l'argument de sleep (), vous devez insérer le calcul directement dans sleep ()


Et le retour de mon terminal

1 ───── 17: 20: 16.891

2 ───── 17: 20: 18.891

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

0
forrest