Misurazione del tempo trascorso con il modulo Time


337

Con il modulo Time in Python è possibile misurare il tempo trascorso? In tal caso, come posso farlo?

Devo farlo in modo che se il cursore è stato in un widget per una certa durata, si verifica un evento.


3
NB: qualsiasi risposta utilizzata time.time()non è corretta. L'esempio più semplice è se l'ora del sistema viene modificata durante il periodo di misurazione.
OrangeDog

Per la tua domanda originale sull'attivazione di un evento se un cursore rimane su una determinata durata su un widget, docs.python.org/3/library/threading.html fornisce tutto ciò di cui hai bisogno, credo. Il multithreading e una variabile di condizione con timeout potrebbero essere una delle soluzioni. Le tue circostanze, tuttavia, al momento non sono chiare per rispondere.
Tora,

2
Non c'è motivo per cui qualcuno dovrebbe usare time.time()per misurare il tempo trascorso nel pitone moderno (influenzato da cambiamenti manuali, deriva, secondi saltanti ecc.). La seguente risposta deve essere più alta, considerando che questa domanda è ora il miglior risultato in Google per la misurazione del tempo trascorso.
NPras,


1
@NPras dimentica "il pitone moderno". Era sempre errato da usare time.time().
OrangeDog,

Risposte:


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

Puoi anche scrivere un semplice decoratore per semplificare la misurazione dei tempi di esecuzione di varie funzioni:

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 = {}

Uso:

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

È possibile profilare più di una funzione contemporaneamente. Quindi per stampare le misure basta chiamare print_prof_data ():


11
Puoi anche dare un'occhiata a Profilehooks pip install profilehooks e alla sua homepage qui
pjama

11
Si noti che da Python 3.3, si dovrebbe probabilmente usare time.monotonic()piuttosto che time.time()quando si misurano i timeout o le durate. docs.python.org/3/library/time.html#time.monotonic
Debilski

39
Vale la pena aggiungere / notare qui che l'unità di misura per il tempo trascorso sarà di secondi.
Eric Kramer,

4
@EricKramer grazie! un mio enorme animale domestico, che spiega le misurazioni senza definire l'unità di misura. E da ragazzo .NET che immergeva le dita dei piedi in Python per la prima volta, ho pensato automaticamente "millisecondi".
Adam Plocher,

2
Non funziona se (ad es.) L'orologio di sistema viene modificato e potrebbe non avere una risoluzione inferiore ai secondi. Risposta corretta: stackoverflow.com/a/47637891/476716
OrangeDog

97

time.time() farà il lavoro.

import time

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

elapsed = end - start

Potresti voler esaminare questa domanda, ma non penso che sarà necessario.


6
Sì, il tempo è in secondi
Eric Kramer,

Dovresti cambiare start in start_time.
Zoran Pandovski,

time.time()è una cattiva idea perché è possibile ripristinare l'orologio di sistema che ti farà tornare indietro nel tempo. time.monotonic()se ne occupa (monotonico = va solo avanti). time.perf_counter()è anche monotonico ma ha una precisione ancora maggiore, quindi è consigliato per l'ora dell'orologio da parete.
xjcl

76

Per gli utenti che desiderano una formattazione migliore,

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

stamperà, per 2 secondi:

'00:00:02'

e per 7 minuti un secondo:

'00:07:01'

si noti che l'unità di tempo minimo con gmtime è di secondi. Se hai bisogno di microsecondi, considera quanto segue:

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

documentazione strftime


1
Grazie per la tua risposta, che mi ispira. Ho intenzione di utilizzare e = time.time() - start_time ; print("%02d:%02d:%02d" % (e // 3600, (e % 3600 // 60), (e % 60 // 1)))che produce quasi lo stesso, oltre a coprire la situazione che dura più di 24 ore.
Tora,

@Tora potresti voler controllare "{}". Format () invece di% 02d per futuri problemi di compatibilità.
Rutger Hofste,

2
grazie! Ora mi sto abituando a quello nuovo. '{: 02d}: {: 02d}: {: 02d}'. Formato (e // 3600, (e% 3600 // 60), e% 60)
Tora,

puoi usare time.monotonic()come nelle altre risposte?
endolith

elapsed.secondssarà errato se la durata è superiore a un giorno. Vuoi elapsed.total_seconds()essere resistente
Ash Berlin-Taylor,

51

Per la migliore misura del tempo trascorso (da Python 3.3), usare time.perf_counter().

Restituisce il valore (in secondi frazionari) di un contatore delle prestazioni, ovvero un orologio con la massima risoluzione disponibile per misurare una breve durata. Include il tempo trascorso durante il sonno ed è a livello di sistema. Il punto di riferimento del valore restituito non è definito, pertanto è valida solo la differenza tra i risultati delle chiamate consecutive.

Per le misurazioni nell'ordine di ore / giorni, non ti interessa la risoluzione dei secondi, quindi usa time.monotonic()invece.

Restituisce il valore (in secondi frazionari) di un orologio monotonico, ovvero un orologio che non può tornare indietro. L'orologio non è interessato dagli aggiornamenti dell'orologio di sistema. Il punto di riferimento del valore restituito non è definito, pertanto è valida solo la differenza tra i risultati delle chiamate consecutive.

In molte implementazioni, queste possono effettivamente essere la stessa cosa.

Prima della 3.3, sei bloccato con time.clock().

Su Unix, restituisce il tempo corrente del processore come un numero in virgola mobile espresso in secondi. La precisione, e in effetti la definizione stessa del significato di "tempo del processore", dipende da quella della funzione C con lo stesso nome.

Su Windows, questa funzione restituisce i secondi dell'orologio da parete trascorsi dalla prima chiamata a questa funzione, come numero in virgola mobile, in base alla funzione Win32 QueryPerformanceCounter (). La risoluzione è in genere migliore di un microsecondo.


Aggiornamento per Python 3.7

Una novità di Python 3.7 è PEP 564 - Aggiungi nuove funzioni temporali con una risoluzione di nanosecondi.

L'uso di questi può ulteriormente eliminare gli errori di arrotondamento e virgola mobile, soprattutto se si misurano periodi molto brevi o se l'applicazione (o la macchina Windows) è di lunga durata.

La risoluzione inizia a peggiorare perf_counter()dopo circa 100 giorni. Quindi, ad esempio, dopo un anno di attività, l'intervallo più breve (maggiore di 0) che può misurare sarà maggiore di quando è stato avviato.


Aggiornamento per Python 3.8

time.clock ora è andato.


"In molte implementazioni, queste potrebbero effettivamente essere la stessa cosa." È vero, sul mio PC Linux Mint, time.monotonic () e time.perf_counter () sembrano restituire valori identici.
xjcl

7

Per un periodo più lungo.

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

stamperebbe

00:03:15

se più di 24 ore

25:33:57

Ciò è ispirato dalla risposta di Rutger Hofste. Grazie Rutger!


6

È necessario importare l'ora e quindi utilizzare il metodo time.time () per conoscere l'ora corrente.

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 

3

Un altro bel modo di cronometrare le cose è usare la struttura with python.

con struttura chiama automaticamente i metodi __enter__ e __exit__ che è esattamente ciò di cui abbiamo bisogno per cronometrare le cose.

Creiamo una 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))

Quindi, si può usare la classe Timer in questo modo:

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

Il risultato è il seguente:

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]

Tempo trascorso per il calcolo di alcuni numeri primi: 5.01704216003418ms


2

La risposta di Vadim Shender è fantastica. Puoi anche usare un decoratore più semplice come di seguito:

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!")

1

Nella programmazione, ci sono 2 modi principali per misurare il tempo , con risultati diversi:

>>> 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
  • Tempo del processore : indica quanto tempo questo processo specifico impiega attivamente per essere eseguito sulla CPU. La sospensione, l'attesa di una richiesta Web o il momento in cui vengono eseguiti solo altri processi non contribuiranno a questo.

    • Uso time.process_time()
  • Orologio da parete : si riferisce a quanto tempo è trascorso "su un orologio appeso al muro", cioè al di fuori del tempo reale.

    • Uso time.perf_counter()

      • time.time() misura anche l'ora dell'orologio da parete ma può essere ripristinata, in modo da poter tornare indietro nel tempo
      • time.monotonic() non può essere ripristinato (monotonico = va solo avanti) ma ha una precisione inferiore a time.perf_counter()

0

Ecco un aggiornamento al codice intelligente di Vadim Shender con output tabulare:

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.