Mesurer le temps écoulé avec le module Time

337

Avec le module Time en python, est-il possible de mesurer le temps écoulé? Si oui, comment dois-je procéder?

Je dois le faire pour que si le curseur se trouve dans un widget pendant une certaine durée, un événement se produit.

rectangletangle
la source
3
NB: toute réponse utilisant time.time()est incorrecte. L'exemple le plus simple est si l'heure du système est modifiée pendant la période de mesure.
OrangeDog
Pour votre question initiale concernant le déclenchement d'un événement si un curseur reste pendant une certaine durée sur un widget, docs.python.org/3/library/threading.html fournit tout ce dont vous avez besoin, je pense. Le multithreading et une variable de condition avec timeout peuvent être l'une des solutions. Cependant, votre situation n'est actuellement pas claire pour répondre.
Tora
2
Il n'y a aucune raison que quelqu'un devrait utiliser time.time()pour mesurer le temps écoulé en python moderne (affecté par les changements manuels, la dérive, les secondes intercalaires, etc.). Cette réponse ci-dessous doit être plus élevée, étant donné que cette question est désormais le meilleur résultat de Google pour mesurer le temps écoulé.
NPras
Vous pouvez également mesurer le temps avec le profileur cProfile: docs.python.org/3/library/profile.html#module-cProfile stackoverflow.com/questions/582336/…
Anton Tarasenko
1
@NPras oublie "python moderne". C'était toujours incorrect à utiliser time.time().
OrangeDog

Réponses:

514
start_time = time.time()
# your code
elapsed_time = time.time() - start_time

Vous pouvez également écrire un décorateur simple pour simplifier la mesure du temps d'exécution de diverses fonctions:

import time
from functools import wraps

PROF_DATA = {}

def profile(fn):
    @wraps(fn)
    def with_profiling(*args, **kwargs):
        start_time = time.time()

        ret = fn(*args, **kwargs)

        elapsed_time = time.time() - start_time

        if fn.__name__ not in PROF_DATA:
            PROF_DATA[fn.__name__] = [0, []]
        PROF_DATA[fn.__name__][0] += 1
        PROF_DATA[fn.__name__][1].append(elapsed_time)

        return ret

    return with_profiling

def print_prof_data():
    for fname, data in PROF_DATA.items():
        max_time = max(data[1])
        avg_time = sum(data[1]) / len(data[1])
        print "Function %s called %d times. " % (fname, data[0]),
        print 'Execution time max: %.3f, average: %.3f' % (max_time, avg_time)

def clear_prof_data():
    global PROF_DATA
    PROF_DATA = {}

Usage:

@profile
def your_function(...):
    ...

Vous pouvez profiler plus d'une fonction simultanément. Ensuite, pour imprimer les mesures, appelez simplement print_prof_data ():

Vadim Shender
la source
11
Vous pouvez également jeter un oeil à profilehooks pip install profilehooks , et sa page d'accueil ici
pjama
11
Notez que depuis Python 3.3, on devrait probablement utiliser time.monotonic()plutôt que time.time()lors de la mesure des délais d'attente ou des durées. docs.python.org/3/library/time.html#time.monotonic
Debilski
39
Il convient d'ajouter / de noter ici que l'unité de mesure du temps écoulé sera de secondes.
Eric Kramer
4
@EricKramer merci! une énorme bête noire, expliquant les mesures sans définir l'unité de mesure. Et en tant que gars .NET plongeant ses orteils dans Python pour la première fois, j'ai automatiquement pensé "millisecondes".
Adam Plocher
2
Ne fonctionne pas si (par exemple) l'horloge système est modifiée et peut ne pas avoir une résolution inférieure à la seconde. Bonne réponse: stackoverflow.com/a/47637891/476716
OrangeDog
97

time.time() fera le travail.

import time

start = time.time()
# run your code
end = time.time()

elapsed = end - start

Vous voudrez peut-être examiner cette question, mais je ne pense pas que ce sera nécessaire.

lalli
la source
6
Oui, le temps est en secondes
Eric Kramer
Vous devez changer start en start_time.
Zoran Pandovski
time.time()est une mauvaise idée car l'horloge système peut être réinitialisée, ce qui vous fera remonter le temps. time.monotonic()s'occupe de cela (monotone = il ne fait que progresser). time.perf_counter()est également monotone mais a une précision encore plus élevée, il est donc recommandé pour l'heure de l'horloge murale.
xjcl
76

Pour les utilisateurs qui souhaitent un meilleur formatage,

import time
start_time = time.time()
# your script
elapsed_time = time.time() - start_time
time.strftime("%H:%M:%S", time.gmtime(elapsed_time))

imprimera, pendant 2 secondes:

'00:00:02'

et pendant 7 minutes une seconde:

'00:07:01'

notez que l'unité de temps minimum avec gmtime est de secondes. Si vous avez besoin de microsecondes, tenez compte des éléments suivants:

import datetime
start = datetime.datetime.now()
# some code
end = datetime.datetime.now()
elapsed = end - start
print(elapsed)
# or
print(elapsed.seconds,":",elapsed.microseconds) 

documentation strftime

Rutger Hofste
la source
1
Merci pour votre réponse qui m'inspire. Je vais utiliser e = time.time() - start_time ; print("%02d:%02d:%02d" % (e // 3600, (e % 3600 // 60), (e % 60 // 1)))cela donne presque le même ainsi que couvrir la situation qui s'est écoulée plus de 24 heures.
Tora
@Tora, vous voudrez peut-être consulter "{}". Format () au lieu de% 02d pour de futurs problèmes de compatibilité.
Rutger Hofste
2
Merci! Maintenant, je m'habitue au nouveau. '{: 02d}: {: 02d}: {: 02d}'. Format (e // 3600, (e% 3600 // 60), e% 60)
Tora
pouvez-vous utiliser time.monotonic()comme dans les autres réponses?
endolith
elapsed.secondssera incorrect si la durée est supérieure à un jour. Vous voulez elapsed.total_seconds()être résilient
Ash Berlin-Taylor
51

Pour la meilleure mesure du temps écoulé (depuis Python 3.3), utilisez time.perf_counter().

Renvoie la valeur (en secondes fractionnaires) d'un compteur de performances, c'est-à-dire une horloge avec la résolution disponible la plus élevée pour mesurer une courte durée. Il comprend le temps écoulé pendant le sommeil et concerne l'ensemble du système. Le point de référence de la valeur renvoyée n'est pas défini, de sorte que seule la différence entre les résultats des appels consécutifs est valide.

Pour les mesures de l'ordre des heures / jours, vous ne vous souciez pas de la résolution en moins d'une seconde, utilisez-la à la time.monotonic()place.

Renvoie la valeur (en fraction de seconde) d'une horloge monotone, c'est-à-dire une horloge qui ne peut pas reculer. L'horloge n'est pas affectée par les mises à jour de l'horloge système. Le point de référence de la valeur renvoyée n'est pas défini, de sorte que seule la différence entre les résultats des appels consécutifs est valide.

Dans de nombreuses implémentations, cela peut en fait être la même chose.

Avant la 3.3, vous êtes coincé avec time.clock().

Sous Unix, renvoyez le temps processeur actuel sous la forme d'un nombre à virgule flottante exprimé en secondes. La précision, et en fait la définition même de la signification du «temps processeur», dépend de celle de la fonction C du même nom.

Sous Windows, cette fonction renvoie les secondes de l'horloge murale écoulées depuis le premier appel à cette fonction, sous la forme d'un nombre à virgule flottante, basé sur la fonction Win32 QueryPerformanceCounter (). La résolution est généralement meilleure qu'une microseconde.


Mise à jour pour Python 3.7

Nouveau dans Python 3.7 est le PEP 564 - Ajoutez de nouvelles fonctions temporelles avec une résolution en nanosecondes.

Leur utilisation peut éliminer davantage les erreurs d'arrondi et de virgule flottante, surtout si vous mesurez des périodes très courtes ou si votre application (ou votre machine Windows) est longue.

La résolution commence à s'effondrer perf_counter()après environ 100 jours. Ainsi, par exemple, après une année de disponibilité, l'intervalle le plus court (supérieur à 0) qu'il peut mesurer sera plus grand que lorsqu'il a commencé.


Mise à jour pour Python 3.8

time.clock est maintenant parti.

OrangeDog
la source
"Dans de nombreuses implémentations, cela peut en fait être la même chose." Certes, sur mon PC Linux Mint, time.monotonic () et time.perf_counter () semblent renvoyer des valeurs identiques.
xjcl
7

Pour une période plus longue.

import time
start_time = time.time()
...
e = int(time.time() - start_time)
print('{:02d}:{:02d}:{:02d}'.format(e // 3600, (e % 3600 // 60), e % 60))

imprimerait

00:03:15

si plus de 24 heures

25:33:57

Cela est inspiré par la réponse de Rutger Hofste. Merci Rutger!

Tora
la source
6

Vous devez importer l'heure, puis utiliser la méthode time.time () pour connaître l'heure actuelle.

import time

start_time=time.time() #taking current time as starting time

#here your code

elapsed_time=time.time()-start_time #again taking current time - starting time 
Nurul Akter Towhid
la source
3

Une autre bonne façon de chronométrer les choses est d'utiliser la structure with python.

avec structure appelle automatiquement __enter__ et __exit__ méthodes , ce qui est exactement ce dont nous avons besoin pour chronométrer les choses.

Créons une classe Timer .

from time import time

class Timer():
    def __init__(self, message):
        self.message = message
    def __enter__(self):
        self.start = time()
        return None  # could return anything, to be used like this: with Timer("Message") as value:
    def __exit__(self, type, value, traceback):
        elapsed_time = (time() - self.start) * 1000
        print(self.message.format(elapsed_time))

Ensuite, on peut utiliser la classe Timer comme ceci:

with Timer("Elapsed time to compute some prime numbers: {}ms"):
    primes = []
    for x in range(2, 500):
        if not any(x % p == 0 for p in primes):
            primes.append(x)
    print("Primes: {}".format(primes))

Le résultat est le suivant:

Primes: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89 , 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227 , 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373 , 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499]

Temps écoulé pour calculer certains nombres premiers: 5,01704216003418ms

TM
la source
2

La réponse de Vadim Shender est excellente. Vous pouvez également utiliser un décorateur plus simple comme ci-dessous:

import datetime
def calc_timing(original_function):                            
    def new_function(*args,**kwargs):                        
        start = datetime.datetime.now()                     
        x = original_function(*args,**kwargs)                
        elapsed = datetime.datetime.now()                      
        print("Elapsed Time = {0}".format(elapsed-start))     
        return x                                             
    return new_function()  

@calc_timing
def a_func(*variables):
    print("do something big!")
Mohammad
la source
1

En programmation, il existe 2 façons principales de mesurer le temps , avec des résultats différents:

>>> print(time.process_time()); time.sleep(10); print(time.process_time())
0.11751394000000001
0.11764988400000001  # took  0 seconds and a bit
>>> print(time.perf_counter()); time.sleep(10); print(time.perf_counter())
3972.465770326
3982.468109075       # took 10 seconds and a bit
  • Temps processeur : c'est la durée pendant laquelle ce processus spécifique passe activement à s'exécuter sur le processeur. La mise en veille, l'attente d'une demande Web ou le moment où seuls d'autres processus sont exécutés n'y contribueront pas.

    • Utilisation time.process_time()
  • Horloge murale : il s'agit du temps qui s'est écoulé "sur une horloge suspendue au mur", c'est-à-dire en dehors du temps réel.

    • Utilisation time.perf_counter()

      • time.time() mesure également l'heure de l'horloge murale mais peut être réinitialisée, vous pouvez donc remonter dans le temps
      • time.monotonic() ne peut pas être réinitialisé (monotone = ne fait que progresser) mais a une précision inférieure à time.perf_counter()
xjcl
la source
0

Voici une mise à jour du code intelligent de Vadim Shender avec sortie tabulaire:

import collections
import time
from functools import wraps

PROF_DATA = collections.defaultdict(list)

def profile(fn):
    @wraps(fn)
    def with_profiling(*args, **kwargs):
        start_time = time.time()
        ret = fn(*args, **kwargs)
        elapsed_time = time.time() - start_time
        PROF_DATA[fn.__name__].append(elapsed_time)
        return ret
    return with_profiling

Metrics = collections.namedtuple("Metrics", "sum_time num_calls min_time max_time avg_time fname")

def print_profile_data():
    results = []
    for fname, elapsed_times in PROF_DATA.items():
        num_calls = len(elapsed_times)
        min_time = min(elapsed_times)
        max_time = max(elapsed_times)
        sum_time = sum(elapsed_times)
        avg_time = sum_time / num_calls
        metrics = Metrics(sum_time, num_calls, min_time, max_time, avg_time, fname)
        results.append(metrics)
    total_time = sum([m.sum_time for m in results])
    print("\t".join(["Percent", "Sum", "Calls", "Min", "Max", "Mean", "Function"]))
    for m in sorted(results, reverse=True):
        print("%.1f\t%.3f\t%d\t%.3f\t%.3f\t%.3f\t%s" % (100 * m.sum_time / total_time, m.sum_time, m.num_calls, m.min_time, m.max_time, m.avg_time, m.fname))
    print("%.3f Total Time" % total_time)
Steve
la source