it-swarm.it

Misurare il tempo trascorso in Python?

Quello che voglio è iniziare a contare il tempo da qualche parte nel mio codice e poi ottenere il tempo trascorso, per misurare il tempo necessario per eseguire poche funzioni. Penso che stia usando il modulo timeit in modo errato, ma i documenti sono semplicemente confusi per me.

import timeit

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

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 da 3.3 potrebbe essere quella di usare perf_counter o process_time , a seconda delle tue esigenze. Prima di 3.3 si consigliava di usare time.clock (grazie Ambra ). Tuttavia, è attualmente deprecato:

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

Su Windows, questa funzione restituisce secondi di orologio a muro trascorsi dal prima chiamata a questa funzione, come numero a virgola mobile, in base al Funzione Win32 QueryPerformanceCounter(). La risoluzione è in genere meglio di un microsecondo.

Obsoleto dalla versione 3.3: Il comportamento di questa funzione dipende da sulla piattaforma: usa perf_counter() o process_time() invece, a seconda delle esigenze, per avere un comportamento ben definito.

1012
NPE

Utilizza timeit.default_timer anziché timeit.timeit. Il primo fornisce automaticamente il miglior orologio disponibile sulla piattaforma e sulla 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. Su Python 3.3+ default_timer is time.perf_counter () su tutte le piattaforme. Vedi Python - time.clock () vs. time.time () - accuratezza?

Guarda anche:

420
jfs

Solo Python 3:

Poiché time.clock () è deprecato da Python 3.3 , si vorrà usare time.perf_counter() per il timing a livello di sistema, o time.process_time() per il timing a livello di processo, proprio come hai usato usare time.clock():

import time

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

La nuova funzione process_time non includerà il tempo trascorso durante il sonno.

99
Pierre Prinetti

Data una funzione che vorresti tempo,

test.py:

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

il modo più semplice per 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 utilizzare time.time o time.clock (ingenuamente) per confrontare la velocità delle funzioni. Possono dare risultati fuorvianti .

PS. Non mettere le dichiarazioni di stampa in una funzione che desideri temporeggiare; altrimenti il ​​tempo misurato dipenderà dalla velocità del terminale .

73
unutbu

Preferisco questo. timeit doc è 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 non c'è alcuna formattazione in corso qui, ho appena scritto hh:mm:ss nella stampa in modo da poter interpretare time_elapsed

45
user1761806

È divertente farlo con un gestore di contesto che memorizza automaticamente l'ora di inizio dopo l'immissione in un blocco with, quindi blocca l'ora di fine all'uscita del blocco. Con un po 'di inganno, è persino possibile 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 contextmanager codice 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 qualche 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 a questa funzione, il valore di ritorno di elapsed() viene congelato all'uscita del blocco e ulteriori chiamate restituiscono la stessa durata (di circa 6 secondi in questo esempio di giocattolo). 

43
gojomo

L'utilizzo di time.time per misurare l'esecuzione ti offre il tempo di esecuzione complessivo dei tuoi comandi, compreso il tempo di esecuzione trascorso da altri processi sul tuo computer. È il momento in cui l'utente se ne accorge, ma non va bene se vuoi confrontare diversi frammenti di codice/algoritmi/funzioni/...

Maggiori informazioni su timeit:

Se vuoi una visione più approfondita della profilazione:

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

24
rocksportrocker

Ecco una piccola classe di timer che restituisce la 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
18
Danijel

I moduli cProfile e pstats di python offrono un grande supporto per misurare il tempo trascorso in certe 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, è sufficiente eseguire:

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

Ciò che sta facendo è utilizzare il modulo cProfile per profilare tutte le funzioni in timeFunctions.py e raccogliere le statistiche nel file timeStats.profile. Si noti che non è stato necessario aggiungere alcun codice al modulo esistente (timeFunctions.py) e ciò può essere fatto con qualsiasi modulo.

Una volta ottenuto il file stats, è possibile eseguire il modulo pstats come segue:

python -m pstats timeStats.profile

Questo esegue il browser delle statistiche interattive che ti offre molte funzionalità di Nizza. Per il tuo caso d'uso particolare puoi semplicemente controllare le statistiche per la tua funzione. Nel nostro esempio, le statistiche di controllo per entrambe le funzioni ci mostrano 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 il profiling.

16
sanchitarora

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

o, se hai bisogno del 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

16
Brian Burns

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

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

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

14
Leonid Ganeline

(Solo con Ipython) è possibile utilizzare % timeit per misurare il tempo di elaborazione medio:

def foo():
    print "hello"

e poi: 

%timeit foo()

il risultato è qualcosa come:

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

su python3:

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

elegante e breve.

9
DmitrySemenov

Una specie di super risposta successiva, ma forse ha uno scopo per 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 "print" è una funzione in Python 3 e non in Python 2.7. Tuttavia, funziona con qualsiasi altra funzione. Saluti!

9
Andreas Herman

Possiamo anche convertire il tempo in un 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
Kamlesh Verma

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

Innanzitutto, si desidera sempre utilizzare timeit e non time.time (e in molti casi API perf per) perché 

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

Ora il problema è che timeit non è così semplice da usare perché ha bisogno di essere configurato e le cose diventano brutte quando si hanno molte importazioni. Idealmente, vuoi solo un decoratore o utilizzare il blocco with e misurare il tempo. Sfortunatamente non c'è nulla di built-in disponibile per questo, quindi ho creato sotto il piccolo modulo di utilità.

Modulo di utilità di cronometraggio

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

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

class MeasureBlockTime:
    def __init__(self,name="(block)", no_print = False, disable_gc = True):
        self.name = name
        self.no_print = no_print
        self.disable_gc = disable_gc
    def __enter__(self):
        if self.disable_gc:
            self.gcold = gc.isenabled()
            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

Come funzioni temporali

Ora puoi cronometrare qualsiasi funzione semplicemente mettendo davanti un decoratore:

import utils

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

Come blocchi del codice temporale

Se vuoi inserire una porzione di tempo del codice, inseriscilo nel blocco with:

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

Ci sono diverse versioni a metà schiena che galleggiano, quindi voglio sottolineare alcuni punti salienti:

  1. Utilizzare il timer da timeit anziché time.time per le ragioni descritte in precedenza.
  2. Disabilita GC durante i tempi.
  3. Decorator accetta funzioni con param nominati o senza nome.
  4. Possibilità di disabilitare la stampa in tempi di blocco (utilizzare with utils.MeasureBlockTime() as t e quindi t.elapsed).
  5. Possibilità di mantenere abilitato gc per i tempi di blocco.
6
Shital Shah

Un altro modo di usare timeit :

from timeit import timeit

def func():
    return 1 + 1

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

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

5
karlpy

Puoi usare timeit.

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

>>> 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 hai bisogno della funzione wrapper se la funzione non ha parametri. 

4
Vlad Bezden

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))
1
Gal Bracha

L'unico modo che posso pensare è usare time.time().

import time
start = time.time()
sleep(5) #just to give it some delay to show it working
finish = time.time()
elapsed = finish - start
print(elapsed)

Spero che ti possa aiutare.

0
Trooper Z