web-dev-qa-db-fra.com

Mesurer le temps écoulé en python

Existe-t-il un moyen/module simple pour correctement mesurer le temps écoulé en python? Je sais que je peux simplement appeler time.time() deux fois et prendre la différence, mais cela donnera des résultats erronés si l'heure du système est modifiée. Certes, cela ne se produit pas très souvent, mais cela indique que je mesure la mauvaise chose.

Utiliser time.time() pour mesurer les durées est incroyablement détourné quand on y pense. Vous prenez la différence de deux mesures de temps absolu qui sont à leur tour construites à partir de mesures de durée (effectuées par des minuteurs) et d'heures absolues connues (définies manuellement ou via ntp), qui ne vous intéressent pas du tout.

Alors, existe-t-il un moyen d'interroger directement ce "temps de minuterie"? J'imagine qu'il peut être représenté comme une valeur en millisecondes ou microsecondes qui n'a pas de représentation absolue significative (et n'a donc pas besoin d'être ajusté avec le temps du système). En regardant un peu, il semble que c'est exactement ce que fait System.nanoTime() en Java, mais je n'ai pas trouvé de fonction correspondante Python, même si elle le devrait (techniquement sur le plan matériel)) être plus facile à fournir que time.time().

Modifier: pour éviter toute confusion et répondre aux réponses ci-dessous: il ne s'agit pas de modifications DST, et je ne veux pas non plus de temps CPU - je veux du temps physique écoulé. Il n'a pas besoin d'être très fin, ni même particulièrement précis. Cela ne devrait tout simplement pas me donner des durées négatives ou des durées qui sont décalées de plusieurs ordres de grandeur (au-dessus de la granularité), simplement parce que quelqu'un a décidé de régler l'horloge système sur une valeur différente. Voici ce que les documentaires Python disent à propos de 'time.time ()':

"Bien que cette fonction renvoie normalement des valeurs non décroissantes, elle peut renvoyer une valeur inférieure à un appel précédent si l'horloge système a été réglée entre les deux appels"

C'est exactement ce que je veux éviter, car cela peut conduire à des choses étranges comme des valeurs négatives dans les calculs de temps. Je peux contourner cela pour le moment, mais je pense que c'est une bonne idée d'apprendre à utiliser les solutions appropriées lorsque cela est possible, car les kludges reviendront vous mordre un jour.

Edit2: Certaines recherches montrent que vous pouvez obtenir une mesure indépendante du temps système comme je le souhaite dans Windows en utilisant GetTickCount64 (), sous Linux, vous pouvez l'obtenir dans la valeur de retour de times (). Cependant, je ne trouve toujours pas de module qui fournit cette fonctionnalité en Python.

49
Medo42

Ce que vous semblez rechercher est un minuterie monotone . A référence de temps monotone ne saute ni ne recule.

Il y a eu plusieurs tentatives pour implémenter une horloge monotomique multiplateforme pour Python basé sur la référence du système d'exploitation de celui-ci. (Windows, POSIX et BSD sont assez différents) Voir les discussions et certaines des tentatives de temps monotone dans this SO post .

Généralement, vous pouvez simplement utiliser os.times ():

os.times ()

Renvoyez un 5-Tuple de nombres à virgule flottante indiquant les temps accumulés (processeur ou autre), en secondes. Les éléments sont les suivants: heure utilisateur, heure système, heure utilisateur des enfants, heure système des enfants et temps réel écoulé depuis un point fixe dans le passé, dans cet ordre. Voir les temps de page de manuel Unix (2) ou la documentation correspondante de l'API Windows Platform. Sous Windows, seuls les deux premiers éléments sont remplis, les autres sont nuls.

Disponibilité: Unix, Windows

Mais cela ne remplit pas le temps réel écoulé nécessaire (le cinquième tuple) sous Windows.

Si vous avez besoin de la prise en charge de Windows, envisagez ctypes et vous pouvez appeler directement GetTickCount64 (), comme cela a été fait dans cette recette .

10
the wolf

Pour mesurer le temps CPU écoulé, regardez time.clock () . C'est l'équivalent du champ d'heure utilisateur times () de Linux.

Pour l'analyse comparative, utilisez timeit .

Le module datetime , qui fait partie de Python 2.3 + , a également un temps microseconde s'il est pris en charge par la plate-forme.

Exemple:

>>> 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 vous êtes préoccupé par les changements d'heure système (de DS -> ST) vérifiez simplement l'objet renvoyé par datetime. Probablement, l'heure système pourrait avoir un petit ajustement d'un NTP ajustement de référence. Cela devrait être tourné , et les corrections sont appliquées progressivement , mais les battements de synchronisation ntp peuvent avoir un effet avec très petites références temporelles (millisec ou microsec).

Vous pouvez également référencer fonction C d'Alex Martelli si vous voulez quelque chose de cette résolution. Je n'irais pas trop loin pour réinventer la roue. Un temps précis est basique et la plupart des OS modernes font un très bon travail.

Modifier

Sur la base de vos clarifications, il semble que vous ayez besoin d'une simple vérification latérale si l'horloge du système a changé. Il suffit de comparer avec un serveur ntp local convivial:

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 est précis en millisecondes sur Internet et a une résolution de représentation de résolution de 2 à 32 secondes (233 picosecondes). Devrait être assez bon?

Sachez que la structure de données NTP 64 bits débordera en 2036 et tous les 136 ans par la suite - si vous voulez vraiment une solution robuste, mieux vérifier le débordement .. .

24
dawg

Python 3.3 a ajouté un temporisateur monotone dans la bibliothèque standard, qui fait exactement ce que je cherchais. Merci à Paddy3118 pour l'avoir signalé dans "Comment obtenir des durées monotoniques en python?" .

11
Medo42
>>> import datetime
>>> t1=datetime.datetime.utcnow()
>>> t2=datetime.datetime.utcnow()
>>> t2-t1
datetime.timedelta(0, 8, 600000)

L'utilisation de l'UTC évite les périodes embarrassantes où l'horloge change en raison de l'heure d'été.

En ce qui concerne l'utilisation d'une méthode alternative plutôt que de soustraire deux horloges, sachez que le système d'exploitation contient réellement une horloge qui est initialisée à partir d'une horloge matérielle dans le PC. Les implémentations de système d'exploitation modernes garderont également cette horloge synchronisée avec une source officielle afin qu'elle ne dérive pas. C'est beaucoup plus précis que n'importe quel minuteur d'intervalle que le PC peut exécuter.

5
Mark Ransom

Les exemples de fonctions que vous indiquez dans votre édition sont deux choses complètement différentes:

  1. Linux times () renvoie les temps de traitement en millisecondes CPU. L'équivalent de Python est time.clock () ou os.times().
  2. Windows GetTickCount64 () renvoie la disponibilité du système.

Bien que deux fonctions différentes, les deux (potentiellement) pourraient être utilisées pour révéler une horloge système qui avait un "burp" avec ces méthodes:

D'abord:

Vous pouvez prendre à la fois un temps système avec time.time() et un temps CPU avec time.clock(). Étant donné que le temps de l'horloge murale sera TOUJOURS supérieur ou égal au temps CPU, supprimez toutes les mesures où l'intervalle entre les deux lectures time.time() est inférieur aux lectures de contrôle time.clock() appariées.

Exemple:

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... 

Deuxième:

Obtenir la disponibilité du système est également prometteur si vous êtes préoccupé par l'horloge du système, car une réinitialisation utilisateur ne réinitialise pas le nombre de ticks de disponibilité dans la plupart des cas. (que je connais ...)

Maintenant, la question la plus difficile: obtenir une disponibilité du système d'une manière indépendante de la plate-forme - en particulier sans engendrer un nouveau Shell - avec une précision inférieure à la seconde. Hmmm ...

Le meilleur pari est probablement psutil . En parcourant la source , ils utilisent uptime = GetTickCount() / 1000.00f; pour Windows et sysctl "kern.boottime" Pour BSD/OS X, etc. Malheureusement, ce sont tous une résolution de 1 seconde.

2
user648852
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...
2
msudder