Come misurare il tempo trascorso in Python?


1211

Quello che voglio è iniziare a contare il tempo da qualche parte nel mio codice e quindi ottenere il tempo trascorso, per misurare il tempo impiegato per eseguire alcune funzioni. Penso che sto usando il modulo timeit nel modo sbagliato, ma i documenti sono solo confusi per me.

import timeit

start = timeit.timeit()
print("hello")
end = timeit.timeit()
print(end - start)

Risposte:


1456

Se vuoi solo misurare il tempo di orologio da parete trascorso tra due punti, puoi usare time.time():

import time

start = time.time()
print("hello")
end = time.time()
print(end - start)

Questo dà il tempo di esecuzione in secondi.

Un'altra opzione dal 3.3 potrebbe essere quella di utilizzare perf_countero process_time, a seconda delle esigenze. Prima della 3.3 era consigliato l'uso time.clock(grazie all'ambra ). Tuttavia, è attualmente deprecato:

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 un numero in virgola mobile, basato sulla funzione Win32 QueryPerformanceCounter(). La risoluzione è in genere migliore di un microsecondo.

Obsoleto dalla versione 3.3 : il comportamento di questa funzione dipende dalla piattaforma: utilizzare perf_counter()o process_time()invece , a seconda delle proprie esigenze, avere un comportamento ben definito.


17
e per i microsecondi, utilizzare datetime.time ()
Inca

110
(Per la misurazione delle prestazioni, in time.clock()realtà è preferito, dal momento che non può essere interferito con l'orologio di sistema, ma per .time()lo più raggiunge lo stesso scopo.)
Ambra

4
Penso che Python -mtimeit sia molto meglio in quanto funziona più volte ed è costruito come un modo nativo per misurare il tempo in Python
Visgean Skeloru

4
C'è un buon modo per convertire il tempo di esposizione risultante in secondi in qualcosa come HH: MM :: SS?
Danijel,

12
@Danijel: print(timedelta(seconds=execution_time)). Sebbene sia una domanda separata.
jfs,

689

Usa timeit.default_timerinvece di timeit.timeit. Il primo fornisce automaticamente il miglior orologio disponibile sulla tua piattaforma e versione di Python:

from timeit import default_timer as timer

start = timer()
# ...
end = timer()
print(end - start) # Time in seconds, e.g. 5.38091952400282

timeit.default_timer è assegnato a time.time () o time.clock () a seconda del sistema operativo. In Python 3.3+ default_timer è time.perf_counter () su tutte le piattaforme. Vedi Python - time.clock () vs. time.time () - accuratezza?

Guarda anche:


29
Risposta eccellente: l'uso di timeit produrrà risultati molto più accurati poiché renderà automaticamente conto di cose come la raccolta dei rifiuti e le differenze del sistema operativo
lkgarrison,

1
Questo da tempo in ms o secondi?
Katie

3
@KhushbooTiwari in pochi secondi.
jfs,

5
Penso che questa nota dalla documentazione ufficiale debba essere aggiuntadefault_timer() measurations can be affected by other programs running on the same machine, so the best thing to do when accurate timing is necessary is to repeat the timing a few times and use the best time. The -r option is good for this; the default of 3 repetitions is probably enough in most cases. On Unix, you can use time.clock() to measure CPU time.
KGS

1
@KGS: la misurazione delle prestazioni è molto complicata in modo sottile (è facile indurre in errore te stesso). Ci sono molte altre osservazioni che potrebbero essere rilevanti qui. Segui i link nella risposta. Potresti anche essere interessato al perfmodulo (inesistente al momento della risposta) che fornisce la stessa interfaccia ma a volte prende timeitdecisioni diverse dal modulo su come misurare le prestazioni temporali.
jfs,

129

Solo Python 3:

Poiché time.clock () è obsoleto a partire da Python 3.3 , ti consigliamo di utilizzarlo time.perf_counter()per il timing a livello di sistema o time.process_time()per il timing a livello di processo, proprio come in passato time.clock():

import time

t = time.process_time()
#do some stuff
elapsed_time = time.process_time() - t

La nuova funzione process_timenon includerà il tempo trascorso durante il sonno.


28
Usatimeit.default_timer invece di time.perf_counter. Il primo sceglierà il timer appropriato per misurare le prestazioni temporali ottimizzate per la tua piattaforma e versione Python. process_time()fa non includono il tempo durante il sonno e, pertanto, non è appropriato per misurare il tempo trascorso.
jfs,

2
Sto usando l'implementazione suggerita da Pierre, i valori sono indicati in pochi secondi?
ugotchi,

Questa risposta sembra fuori tema (beh, la domanda non era molto specifica). Esistono due misurazioni del "tempo": il tempo dell'orologio a muro tra due punti, del consumo di CPU del processo.
Franklin Piat,

87

Data una funzione che vorresti cronometrare,

test.py:

def foo(): 
    # print "hello"   
    return "hello"

il modo più semplice da usare timeitè chiamarlo dalla riga di comando:

% python -mtimeit -s'import test' 'test.foo()'
1000000 loops, best of 3: 0.254 usec per loop

Non provare a usare time.timeo time.clock(ingenuamente) per confrontare la velocità delle funzioni. Possono dare risultati fuorvianti .

PS. Non inserire dichiarazioni di stampa in una funzione che si desidera impostare; altrimenti il ​​tempo misurato dipenderà dalla velocità del terminale .


65

È divertente farlo con un gestore di contesto che ricorda automaticamente l'ora di inizio all'entrata in un withblocco, quindi congela l'ora di fine all'uscita del blocco. Con un po 'di trucco, puoi persino ottenere un conteggio del tempo trascorso all'interno del blocco dalla stessa funzione di gestione del contesto.

La libreria principale non ha questo (ma probabilmente dovrebbe). Una volta sul posto, puoi fare cose come:

with elapsed_timer() as elapsed:
    # some lengthy code
    print( "midpoint at %.2f seconds" % elapsed() )  # time so far
    # other lengthy code

print( "all done at %.2f seconds" % elapsed() )

Ecco il codice di contextmanager sufficiente per fare il trucco:

from contextlib import contextmanager
from timeit import default_timer

@contextmanager
def elapsed_timer():
    start = default_timer()
    elapser = lambda: default_timer() - start
    yield lambda: elapser()
    end = default_timer()
    elapser = lambda: end-start

E un po 'di codice demo eseguibile:

import time

with elapsed_timer() as elapsed:
    time.sleep(1)
    print(elapsed())
    time.sleep(2)
    print(elapsed())
    time.sleep(3)

Si noti che in base alla progettazione di questa funzione, il valore restituito di elapsed() viene congelato all'uscita del blocco e ulteriori chiamate restituiscono la stessa durata (di circa 6 secondi in questo esempio di giocattolo).


2
Altro esempio di gestore di contesto: dabeaz.blogspot.fr/2010/02/…
Jérôme,

1
@ Jérôme bell'esempio - L'ho adattato come un'altra risposta - stackoverflow.com/a/41408510/243392
Brian Burns

62

Tempo di misurazione in secondi:

from timeit import default_timer as timer
from datetime import timedelta

start = timer()
end = timer()
print(timedelta(seconds=end-start))

Uscita :

0:00:01.946339

1
Questa è la risposta più concisa con l'output più pulito.
Dave Liu,

56

Preferisco questo. timeitdoc è troppo confuso.

from datetime import datetime 

start_time = datetime.now() 

# INSERT YOUR CODE 

time_elapsed = datetime.now() - start_time 

print('Time elapsed (hh:mm:ss.ms) {}'.format(time_elapsed))

Nota che qui non c'è nessuna formattazione, ho appena scritto hh:mm:ssnella stampa in modo che si possa interpretaretime_elapsed


Mi è stato detto che il timeit calcola il tempo della CPU, il datetime tiene conto anche del tempo della CPU utilizzato? Sono la stessa cosa?
Sreehari R

3
È rischioso misurare il tempo trascorso in questo modo perché datetime.now () può cambiare tra le due chiamate per motivi come la sincronizzazione dell'ora di rete, la commutazione dell'ora legale o l'utente che suona l'orologio.
user1318499

45

Ecco un altro modo per farlo:

>> from pytictoc import TicToc
>> t = TicToc() # create TicToc instance
>> t.tic() # Start timer
>> # do something
>> t.toc() # Print elapsed time
Elapsed time is 2.612231 seconds.

Confronto con il modo tradizionale:

>> from time import time
>> t1 = time()
>> # do something
>> t2 = time()
>> elapsed = t2 - t1
>> print('Elapsed time is %f seconds.' % elapsed)
Elapsed time is 2.612231 seconds.

Installazione:

pip install pytictoc

Fare riferimento alla pagina PyPi per maggiori dettagli.


13
Sarebbe utile spiegare il vantaggio di utilizzare questa libreria rispetto ad altri approcci.
hlg

La funzionalità nidificata è effettivamente interrotta. Ho aperto un problema che descriveva dove si trova il problema nel codice ma il repository non è stato mantenuto da un anno, quindi non mi aspetto un cambiamento.
PetarMI,

Trovo che l'annidamento sia un po 'confuso. Se dovessi imbattermi t.tic()nel codice sepolto, spetta a me lo sviluppatore tenere un elenco mentale di dove nella serie dovrei aspettarmi che questo sia. Ti ritrovi a creare nidi o solo più tictoc?
ScottieB,

1
@PetarMI: Cordiali saluti, ho appena risolto il problema con ttictoc. Ho avuto un bel casino, ma ora dovrebbe andare bene.
H. Sánchez,

33

Ecco le mie scoperte dopo aver esaminato molte buone risposte qui e alcuni altri articoli.

Innanzitutto, se stai discutendo tra timeitetime.time , timeithanno due vantaggi:

  1. timeit seleziona il miglior timer disponibile sul tuo sistema operativo e sulla versione di Python.
  2. timeit disabilita la garbage collection, tuttavia, questo non è qualcosa che potresti o non potresti desiderare.

Ora il problema è che timeitnon è così semplice da usare perché ha bisogno di installazione e le cose si fanno brutte quando hai un sacco di importazioni. Idealmente, vuoi solo un decoratore o usarewith blocco e misurare il tempo. Sfortunatamente, non è disponibile nulla per questo, quindi hai due opzioni:

Opzione 1: utilizzare la libreria timebudget

Il timebudget è una libreria versatile e molto semplice che puoi usare solo in una riga di codice dopo l'installazione pip.

@timebudget  # Record how long this function takes
def my_method():
    # my code

Opzione 2: utilizzare direttamente il modulo di codice

Ho creato sotto un piccolo modulo di utilità.

# utils.py
from functools import wraps
import gc
import timeit

def MeasureTime(f, no_print=False, disable_gc=False):
    @wraps(f)
    def _wrapper(*args, **kwargs):
        gcold = gc.isenabled()
        if disable_gc:
            gc.disable()
        start_time = timeit.default_timer()
        try:
            result = f(*args, **kwargs)
        finally:
            elapsed = timeit.default_timer() - start_time
            if disable_gc and gcold:
                gc.enable()
            if not no_print:
                print('"{}": {}s'.format(f.__name__, elapsed))
        return result
    return _wrapper

class MeasureBlockTime:
    def __init__(self,name="(block)", no_print=False, disable_gc=False):
        self.name = name
        self.no_print = no_print
        self.disable_gc = disable_gc
    def __enter__(self):
        self.gcold = gc.isenabled()
        if self.disable_gc:
            gc.disable()
        self.start_time = timeit.default_timer()
    def __exit__(self,ty,val,tb):
        self.elapsed = timeit.default_timer() - self.start_time
        if self.disable_gc and self.gcold:
            gc.enable()
        if not self.no_print:
            print('Function "{}": {}s'.format(self.name, self.elapsed))
        return False #re-raise any exceptions

Ora puoi cronometrare qualsiasi funzione semplicemente posizionandoti davanti un decoratore:

import utils

@utils.MeasureTime
def MyBigFunc():
    #do something time consuming
    for i in range(10000):
        print(i)

Se vuoi cronometrare parte del codice, basta inserirlo nel withblocco:

import utils

#somewhere in my code

with utils.MeasureBlockTime("MyBlock"):
    #do something time consuming
    for i in range(10000):
        print(i)

# rest of my code

vantaggi:

Esistono diverse versioni con il mezzo supporto fluttuanti, quindi desidero sottolineare alcuni punti salienti:

  1. Utilizzare il timer da timeit anziché time.time per i motivi descritti in precedenza.
  2. Se lo desideri, puoi disabilitare GC durante il cronometraggio.
  3. Decorator accetta funzioni con parametri con o senza nome.
  4. Possibilità di disabilitare la stampa nei tempi di blocco (usare with utils.MeasureBlockTime() as te quindi t.elapsed).
  5. Possibilità di mantenere abilitato gc per i tempi di blocco.

28

L'uso time.timeper misurare l'esecuzione fornisce il tempo complessivo di esecuzione dei comandi, incluso il tempo di esecuzione impiegato da altri processi sul computer. È l'ora che l'utente se ne accorga, ma non va bene se si desidera confrontare diversi frammenti di codice / algoritmi / funzioni / ...

Ulteriori informazioni su timeit:

Se vuoi avere una visione più approfondita della profilazione:

Aggiornamento : ho usato molto http://pythonhosted.org/line_profiler/ durante l'ultimo anno e lo trovo molto utile e consiglio di usarlo al posto del modulo profilo Pythons.


19

Ecco una piccola classe timer che restituisce una stringa "hh: mm: ss":

class Timer:
  def __init__(self):
    self.start = time.time()

  def restart(self):
    self.start = time.time()

  def get_time_hhmmss(self):
    end = time.time()
    m, s = divmod(end - self.start, 60)
    h, m = divmod(m, 60)
    time_str = "%02d:%02d:%02d" % (h, m, s)
    return time_str

Uso:

# Start timer
my_timer = Timer()

# ... do something

# Get time string:
time_hhmmss = my_timer.get_time_hhmmss()
print("Time elapsed: %s" % time_hhmmss )

# ... use the timer again
my_timer.restart()

# ... do something

# Get time:
time_hhmmss = my_timer.get_time_hhmmss()

# ... etc

17

I moduli python cProfile e pstats offrono un ottimo supporto per misurare il tempo trascorso in alcune funzioni senza dover aggiungere alcun codice attorno alle funzioni esistenti.

Ad esempio se hai uno script python timeFunctions.py:

import time

def hello():
    print "Hello :)"
    time.sleep(0.1)

def thankyou():
    print "Thank you!"
    time.sleep(0.05)

for idx in range(10):
    hello()

for idx in range(100):
    thankyou()

Per eseguire il profiler e generare statistiche per il file, puoi semplicemente eseguire:

python -m cProfile -o timeStats.profile timeFunctions.py

Quello che sta facendo è usare il modulo cProfile per profilare tutte le funzioni in timeFunctions.py e raccogliere le statistiche nel file timeStats.profile. Nota che non abbiamo dovuto aggiungere alcun codice al modulo esistente (timeFunctions.py) e questo può essere fatto con qualsiasi modulo.

Una volta che hai il file stats puoi eseguire il modulo pstats come segue:

python -m pstats timeStats.profile

Questo esegue il browser statistico interattivo che ti offre molte belle funzionalità. Per il tuo particolare caso d'uso puoi semplicemente controllare le statistiche della tua funzione. Nel nostro esempio, il controllo delle statistiche per entrambe le funzioni ci mostra quanto segue:

Welcome to the profile statistics browser.
timeStats.profile% stats hello
<timestamp>    timeStats.profile

         224 function calls in 6.014 seconds

   Random listing order was used
   List reduced from 6 to 1 due to restriction <'hello'>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       10    0.000    0.000    1.001    0.100 timeFunctions.py:3(hello)

timeStats.profile% stats thankyou
<timestamp>    timeStats.profile

         224 function calls in 6.014 seconds

   Random listing order was used
   List reduced from 6 to 1 due to restriction <'thankyou'>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
      100    0.002    0.000    5.012    0.050 timeFunctions.py:7(thankyou)

L'esempio fittizio non fa molto ma ti dà un'idea di cosa si può fare. La parte migliore di questo approccio è che non devo modificare nessuno dei miei codici esistenti per ottenere questi numeri e ovviamente aiutare con la profilazione.


Tutto questo va bene, ma AFAICT misura ancora il tempo della CPU, non l'ora del wall clock.
ShreevatsaR,

1
In realtà c'è un po 'di confusione; sembra che cProfile guardi l'ora dell'orologio da parete per impostazione predefinita. Ho votato la tua risposta.
ShreevatsaR,

Cordiali saluti: Se ottieni python -m pstats timeStats.profile ValueError: bad marshal data (unknown type code)controlla la versione di Python che stai eseguendo. L'ho preso quando ho corso python3 -m cProfile...e python -m pstats. Il mio errore, ma mi ha preso per un secondo, quindi, volevo condividere don't forget consistency. =)
JayRizzo il

17

Ecco un altro gestore di contesto per il codice di temporizzazione -

Uso:

from benchmark import benchmark

with benchmark("Test 1+1"):
    1+1
=>
Test 1+1 : 1.41e-06 seconds

oppure, se è necessario il valore temporale

with benchmark("Test 1+1") as b:
    1+1
print(b.time)
=>
Test 1+1 : 7.05e-07 seconds
7.05233786763e-07

benchmark.py :

from timeit import default_timer as timer

class benchmark(object):

    def __init__(self, msg, fmt="%0.3g"):
        self.msg = msg
        self.fmt = fmt

    def __enter__(self):
        self.start = timer()
        return self

    def __exit__(self, *args):
        t = timer() - self.start
        print(("%s : " + self.fmt + " seconds") % (self.msg, t))
        self.time = t

Adattato da http://dabeaz.blogspot.fr/2010/02/context-manager-for-timing-benchmarks.html


17

Usa il modulo profiler. Dà un profilo molto dettagliato.

import profile
profile.run('main()')

produce qualcosa come:

          5 function calls in 0.047 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.000    0.000 :0(exec)
        1    0.047    0.047    0.047    0.047 :0(setprofile)
        1    0.000    0.000    0.000    0.000 <string>:1(<module>)
        0    0.000             0.000          profile:0(profiler)
        1    0.000    0.000    0.047    0.047 profile:0(main())
        1    0.000    0.000    0.000    0.000 two_sum.py:2(twoSum)

L'ho trovato molto istruttivo.


1
Che cosa è main()? Sarebbe più utile se potessi fornire un semplice esempio di codice.
not2qubit,

15

Mi piace semplice (python 3):

from timeit import timeit

timeit(lambda: print("hello"))

L'output è microsecondi per una singola esecuzione:

2.430883963010274

Spiegazione : timeit esegue la funzione anonima 1 milione di volte per impostazione predefinita e il risultato viene fornito in secondi . Pertanto il risultato per 1 singola esecuzione è lo stesso importo ma in microsecondi in media.


Per le operazioni lente , aggiungi un numero inferiore di iterazioni o potresti aspettare per sempre:

import time

timeit(lambda: time.sleep(1.5), number=1)

L'output è sempre in secondi per il numero totale di iterazioni:

1.5015795179999714

14

(Solo con Ipython) puoi usare % timeit per misurare il tempo medio di elaborazione:

def foo():
    print "hello"

e poi:

%timeit foo()

il risultato è qualcosa di simile:

10000 loops, best of 3: 27 µs per loop

4
Vale la pena ricordare che è possibile passare i flag a% timeit, ad esempio -n specifica quante volte il codice deve essere ripetuto.
raacer,

11

Un altro modo di usare timeit :

from timeit import timeit

def func():
    return 1 + 1

time = timeit(func, number=1)
print(time)

10

su python3:

from time import sleep, perf_counter as pc
t0 = pc()
sleep(1)
print(pc()-t0)

elegante e corto.


cos'è questo? SM?
KIC

9

Una specie di risposta super successiva, ma forse serve a qualcuno. Questo è un modo per farlo che penso sia super pulito.

import time

def timed(fun, *args):
    s = time.time()
    r = fun(*args)
    print('{} execution took {} seconds.'.format(fun.__name__, time.time()-s))
    return(r)

timed(print, "Hello")

Tieni presente che "stampa" è una funzione in Python 3 e non in Python 2.7. Tuttavia, funziona con qualsiasi altra funzione. Saluti!


Come posso stampare tempi molto piccoli? Ricevo sempre 0.0sec
Rowland Mtetezi il

Puoi trasformarlo in un decoratore; questo mi sembra ancora meglio.
Daniel Moskovich,

8

Puoi usare timeit.

Ecco un esempio su come testare naive_func che accetta parametri usando Python REPL:

>>> import timeit                                                                                         

>>> def naive_func(x):                                                                                    
...     a = 0                                                                                             
...     for i in range(a):                                                                                
...         a += i                                                                                        
...     return a                                                                                          

>>> def wrapper(func, *args, **kwargs):                                                                   
...     def wrapper():                                                                                    
...         return func(*args, **kwargs)                                                                  
...     return wrapper                                                                                    

>>> wrapped = wrapper(naive_func, 1_000)                                                                  

>>> timeit.timeit(wrapped, number=1_000_000)                                                              
0.4458435332577161  

Non è necessaria la funzione wrapper se la funzione non ha parametri.


1
A lambdasarebbe più succinto:print(timeit.timeit(lambda: naive_func(1_000), number=1_000_000))
Ciro Santilli 4 冠状 病 六四 事件 法轮功

7

Possiamo anche convertire il tempo in tempo leggibile dall'uomo.

import time, datetime

start = time.clock()

def num_multi1(max):
    result = 0
    for num in range(0, 1000):
        if (num % 3 == 0 or num % 5 == 0):
            result += num

    print "Sum is %d " % result

num_multi1(1000)

end = time.clock()
value = end - start
timestamp = datetime.datetime.fromtimestamp(value)
print timestamp.strftime('%Y-%m-%d %H:%M:%S')

6

Ho creato una libreria per questo, se vuoi misurare una funzione puoi farlo in questo modo


from pythonbenchmark import compare, measure
import time

a,b,c,d,e = 10,10,10,10,10
something = [a,b,c,d,e]

@measure
def myFunction(something):
    time.sleep(0.4)

@measure
def myOptimizedFunction(something):
    time.sleep(0.2)

myFunction(input)
myOptimizedFunction(input)

https://github.com/Karlheinzniebuhr/pythonbenchmark


6

Per ottenere informazioni dettagliate su tutte le chiamate di funzione in modo ricorsivo, eseguire:

%load_ext snakeviz
%%snakeviz

Prende solo quelle 2 righe di codice in un notebook Jupyter e genera un bel diagramma interattivo. Per esempio:

inserisci qui la descrizione dell'immagine

Ecco il codice Ancora una volta, le 2 righe che iniziano con %sono le uniche righe di codice extra necessarie per usare snakeviz:

# !pip install snakeviz
%load_ext snakeviz
import glob
import hashlib

%%snakeviz

files = glob.glob('*.txt')
def print_files_hashed(files):
    for file in files:
        with open(file) as f:
            print(hashlib.md5(f.read().encode('utf-8')).hexdigest())
print_files_hashed(files)

Sembra anche possibile eseguire snakeviz all'esterno dei notebook. Maggiori informazioni sul sito web di snakeviz .


2
import time

def getElapsedTime(startTime, units):
    elapsedInSeconds = time.time() - startTime
    if units == 'sec':
        return elapsedInSeconds
    if units == 'min':
        return elapsedInSeconds/60
    if units == 'hour':
        return elapsedInSeconds/(60*60)

2

Questo esclusivo approccio basato su classi offre una rappresentazione di stringa stampabile, arrotondamenti personalizzabili e un comodo accesso al tempo trascorso come stringa o float. È stato sviluppato con Python 3.7.

import datetime
import timeit


class Timer:
    """Measure time used."""
    # Ref: https://stackoverflow.com/a/57931660/

    def __init__(self, round_ndigits: int = 0):
        self._round_ndigits = round_ndigits
        self._start_time = timeit.default_timer()

    def __call__(self) -> float:
        return timeit.default_timer() - self._start_time

    def __str__(self) -> str:
        return str(datetime.timedelta(seconds=round(self(), self._round_ndigits)))

Uso:

# Setup timer
>>> timer = Timer()

# Access as a string
>>> print(f'Time elapsed is {timer}.')
Time elapsed is 0:00:03.
>>> print(f'Time elapsed is {timer}.')
Time elapsed is 0:00:04.

# Access as a float
>>> timer()
6.841332235
>>> timer()
7.970274425

1

Misura il tempo di esecuzione di piccoli frammenti di codice.

Unità di tempo : misurata in secondi come galleggiante

import timeit
t = timeit.Timer('li = list(map(lambda x:x*2,[1,2,3,4,5]))')
t.timeit()
t.repeat()
>[1.2934070999999676, 1.3335035000000062, 1.422568500000125]

Il metodo repeat () è una comodità per chiamare timeit () più volte e restituire un elenco di risultati.

repeat(repeat=3

Con questo elenco possiamo prendere una media di tutti i tempi.

Per impostazione predefinita, timeit () disattiva temporaneamente la garbage collection durante i tempi. time.Timer () risolve questo problema.

Professionisti:

timeit.Timer () rende i tempi indipendenti più comparabili. Il gc può essere un componente importante delle prestazioni della funzione misurata. In tal caso, gc (garbage collector) può essere riattivato come prima istruzione nella stringa di installazione. Per esempio:

timeit.Timer('li = list(map(lambda x:x*2,[1,2,3,4,5]))',setup='gc.enable()')

Fonte Python Docs !


1

Se vuoi essere in grado di temporizzare comodamente le funzioni, puoi usare un semplice decoratore:

def timing_decorator(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        original_return_val = func(*args, **kwargs)
        end = time.time()
        print("time elapsed in ", func.__name__, ": ", end - start, sep='')
        return original_return_val

    return wrapper

Puoi usarlo su una funzione che vuoi cronometrare in questo modo:

@timing_decorator
def function_to_time():
    time.sleep(1)

Quindi ogni volta che chiami function_to_time, verrà stampato il tempo impiegato e il nome della funzione in fase di cronometraggio.


1

basato sulla soluzione di contextmanager fornita da https://stackoverflow.com/a/30024601/5095636 , di seguito la versione gratuita lambda, come flake8 avverte dell'uso di lambda secondo E731 :

from contextlib import contextmanager
from timeit import default_timer

@contextmanager
def elapsed_timer():
    start_time = default_timer()

    class _Timer():
      start = start_time
      end = default_timer()
      duration = end - start

    yield _Timer

    end_time = default_timer()
    _Timer.end = end_time
    _Timer.duration = end_time - start_time

test:

from time import sleep

with elapsed_timer() as t:
    print("start:", t.start)
    sleep(1)
    print("end:", t.end)

t.start
t.end
t.duration

1

Il modo più semplice per calcolare la durata di un'operazione:

import time

start_time = time.time()
print(time.ctime())

<operations, programs>

print('minutes: ',(time.time() - start_time)/60)

1

Ecco un decoratore accennato abbastanza ben documentato e di tipo completo che utilizzo come utilità generale:

from functools import wraps
from time import perf_counter
from typing import Any, Callable, Optional, TypeVar, cast

F = TypeVar("F", bound=Callable[..., Any])


def timer(prefix: Optional[str] = None, precision: int = 6) -> Callable[[F], F]:
    """Use as a decorator to time the execution of any function.

    Args:
        prefix: String to print before the time taken.
            Default is the name of the function.
        precision: How many decimals to include in the seconds value.

    Examples:
        >>> @timer()
        ... def foo(x):
        ...     return x
        >>> foo(123)
        foo: 0.000...s
        123
        >>> @timer("Time taken: ", 2)
        ... def foo(x):
        ...     return x
        >>> foo(123)
        Time taken: 0.00s
        123

    """
    def decorator(func: F) -> F:
        @wraps(func)
        def wrapper(*args: Any, **kwargs: Any) -> Any:
            nonlocal prefix
            prefix = prefix if prefix is not None else f"{func.__name__}: "
            start = perf_counter()
            result = func(*args, **kwargs)
            end = perf_counter()
            print(f"{prefix}{end - start:.{precision}f}s")
            return result
        return cast(F, wrapper)
    return decorator

Esempio di utilizzo:

from timer import timer


@timer(precision=9)
def takes_long(x: int) -> bool:
    return x in (i for i in range(x + 1))


print(takes_long(10**8))

Produzione:

takes_long: 4.942629056s
True

I doctest possono essere verificati con:

$ python3 -m doctest --verbose -o=ELLIPSIS timer.py

E il tipo suggerisce con:

$ mypy timer.py

1
È fantastico, grazie per averlo condiviso. Non ho incontrato la libreria di battitura o la parola chiave non locale: è divertente trovare cose nuove da imparare. Ho problemi confezionamento mia testa intorno a questo: Callable[[AnyF], AnyF]. Cosa significa?
Danny,

1
@Danny Sulla parte superiore ho definito l'alias del tipo AnyFper dire Callable[..., Any], quindi AnyFè una funzione che può prendere qualsiasi quantità di argomenti di tipo e restituire qualsiasi cosa. Quindi Callable[[AnyF], AnyF]si espanderebbe a Callable[[Callable[..., Any]], Callable[..., Any]]. Questo è il tipo del valore restituito di timeraka il tipo completo di decorator. È una funzione che prende qualsiasi tipo di funzione come unico argomento e restituisce qualsiasi tipo di funzione.
ruohola,

1
Grazie per la spiegazione! Sto ancora cercando di avvolgere completamente la mia testa attorno agli interni dei decoratori. Questo ha aiutato molto!
Danny,
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.