Mesurer le temps écoulé en Python?
ce que je veux c'est commencer à compter le temps quelque part dans mon code et ensuite obtenir le temps passé, pour mesurer le temps qu'il a fallu pour exécuter peu de fonction. Je pense que j'utilise mal le module timeit, mais les docs sont juste déroutants pour moi.
import timeit
start = timeit.timeit()
print "hello"
end = timeit.timeit()
print end - start
20 réponses
si vous voulez simplement mesurer le temps d'horloge mural écoulé entre deux points, vous pouvez utiliser time.time()
:
import time
start = time.time()
print("hello")
end = time.time()
print(end - start)
donne le temps d'exécution en secondes.
une autre option puisque 3.3 pourrait être d'utiliser perf_counter
ou process_time
, selon vos besoins. Avant 3.3, il était recommandé d'utiliser time.clock
(merci Ambre ). Toutefois, il est actuellement déprécié:
sur Unix, renvoie le temps du processeur en cours sous la forme d'un nombre à virgule flottante exprimée en secondes. La précision, et en fait la définition même de la notion de "temps processeur", ne dépend que de la fonction C du même nom.
sur Windows, Cette fonction renvoie les secondes d'horloge murales écoulées depuis le premier appel à cette fonction, comme un nombre à virgule flottante, basé sur la Fonction Win32
QueryPerformanceCounter()
. La résolution est typiquement mieux que la microseconde.déprécié depuis la version 3.3 : le comportement de cette fonction dépend sur la plate-forme: utiliser
perf_counter()
ouprocess_time()
à la place , selon vos besoins, à avoir un comportement défini.
utiliser timeit.default_timer
au lieu de timeit.timeit
. Le premier fournit la meilleure horloge disponible sur votre plate-forme et la version de Python automatiquement:
from timeit import default_timer as timer
start = timer()
# ...
end = timer()
print(end - start) # Time in seconds, e.g. 5.38091952400282
timeit.default_timer est assigné au temps.time() ou de temps.horloge() selon OS. Sur Python 3.3+ default_timer est time.perf_counter() sur toutes les plateformes. Voir Python-time.clock() en fonction du temps.time() - précision?
voir aussi:
Python 3 seulement:
depuis le temps.clock () est déprécié à partir de Python 3.3 , vous voudrez utiliser time.perf_counter()
pour le chronométrage à l'échelle du système, ou time.process_time()
pour le chronométrage à l'échelle du processus, juste la façon dont vous avez utilisé time.clock()
:
import time
t = time.process_time()
#do some stuff
elapsed_time = time.process_time() - t
la nouvelle fonction process_time
n'inclut pas le temps écoulé pendant le sommeil.
étant donné une fonction que vous aimeriez chronométrer,
test.py:
def foo():
# print "hello"
return "hello"
la façon la plus simple d'utiliser timeit
est de l'appeler depuis la ligne de commande:
% python -mtimeit -s'import test' 'test.foo()'
1000000 loops, best of 3: 0.254 usec per loop
N'essayez pas d'utiliser time.time
ou time.clock
(naïvement) pour comparer la vitesse de fonctions. Ils peuvent donner des résultats trompeurs .
PS. Ne mettez pas d'instructions d'impression dans une fonction que vous souhaitez chronométrer; dans le cas contraire, le temps mesuré dépendra de la Vitesse du terminal .
je préfère ça. timeit
doc est beaucoup trop confus.
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))
Note, qu'il n'y a pas de formatage en cours ici, je viens d'écrire hh:mm:ss
dans l'imprimé pour qu'on puisse interpréter time_elapsed
c'est amusant de faire cela avec un gestionnaire de contexte qui se souvient automatiquement de l'Heure de début à l'entrée d'un bloc with
, puis gèle l'Heure de fin sur la sortie du bloc. Avec un peu de ruse, vous pouvez même obtenir un décompte du temps écoulé à l'intérieur du bloc à partir de la même fonction de gestionnaire de contexte.
la bibliothèque principale n'a pas ceci (mais devrait probablement le faire). Une fois en place, vous pouvez faire des choses comme:
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() )
voilà contextmanager code suffisant pour faire l'affaire:
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
et un code de démonstration exécutable:
import time
with elapsed_timer() as elapsed:
time.sleep(1)
print(elapsed())
time.sleep(2)
print(elapsed())
time.sleep(3)
notez que par conception de cette fonction, la valeur de retour de elapsed()
est gelée à la sortie du bloc, et d'autres appels reviennent de la même durée (d'environ 6 secondes dans cet exemple de jouet).
L'utilisation de time.time
pour mesurer l'exécution vous donne le temps d'exécution total de vos commandes, y compris le temps d'exécution passé par d'autres processus sur votre ordinateur. C'est le temps que l'utilisateur remarque, mais ce n'est pas bon si vous voulez comparer différents morceaux de code / algorithmes / fonctions / ...
plus d'information sur timeit
:
si vous voulez un aperçu plus profond dans le profilage:
- http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Profiling_Code
- comment profiler un script python?
Update : j'ai utilisé http://pythonhosted.org/line_profiler / beaucoup au cours de la dernière année et le trouver très utile et recommande de l'utiliser à la place de pythons profile module.
Voici une minuscule classe de minuterie qui renvoie" HH:mm: ss "string:
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
Utilisation:
# 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
les modules python cProfile et pstats offrent un grand support pour mesurer le temps écoulé dans certaines fonctions sans avoir à ajouter de code autour des fonctions existantes.
par exemple si vous avez un 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()
pour exécuter le profileur et générer des statistiques pour le fichier que vous pouvez simplement exécuter:
python -m cProfile -o timeStats.profile timeFunctions.py
ce que cela fait est d'utiliser le module cProfile pour profiler toutes les fonctions timeFunctions.py et la collecte des statistiques dans les timeStats.le fichier de profil. Notez que nous n'avons pas eu à ajouter de code au module existant (timeFunctions.py) et cela peut être fait avec n'importe quel module.
une fois que vous avez le fichier stats, vous pouvez exécuter le module pstats comme suit:
python -m pstats timeStats.profile
cela exécute le navigateur statistique interactif qui vous donne beaucoup de fonctionnalité agréable. Pour votre cas d'utilisation particulier, vous pouvez simplement consulter les statistiques de votre fonction. Dans notre exemple, la vérification des statistiques pour les deux fonctions nous montre ce qui suit:
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'exemple fictif ne fait pas grand-chose, mais vous donne une idée de ce qui peut être fait. La meilleure partie de cette approche est que je n'ai pas à éditer l'un de mes codes existants pour obtenir ces numéros et évidemment aider avec le profilage.
voici un autre gestionnaire de contexte pour le code de synchronisation -
Utilisation:
from benchmark import benchmark
with benchmark("Test 1+1"):
1+1
=>
Test 1+1 : 1.41e-06 seconds
ou, si vous avez besoin de la valeur temporelle
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
adapté de http://dabeaz.blogspot.fr/2010/02/context-manager-for-timing-benchmarks.html
utiliser le module profileur. Il donne un profil détaillé.
import profile
profile.run('main()')
, il renvoie à quelque chose comme:
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)
je l'ai trouvé très instructif.
sur python3:
from time import sleep, perf_counter as pc
t0 = pc()
sleep(1)
print(pc()-t0)
élégant et court.
une sorte de super réponse plus tard, mais peut-être que ça sert un but pour quelqu'un. C'est une façon de le faire que je trouve super propre.
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")
gardez à l'esprit que" print " est une fonction en Python 3 et non Python 2.7. Cependant, il fonctionne avec toute autre fonction. Acclamations!
Nous pouvons également convertir le temps en lisible temps.
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')
j'ai fait une bibliothèque pour cela, si vous voulez mesurer une fonction vous pouvez juste le faire comme ceci
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)
vous pouvez utiliser timeit.
voici un exemple sur la façon de tester naive_func qui prend le paramètre en utilisant 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
vous n'avez pas besoin de fonction wrapper si la fonction n'a pas de paramètres.
Voici mes conclusions après avoir traversé beaucoup de bonnes réponses ici, ainsi que quelques autres articles.
tout D'abord, vous voulez toujours utiliser timeit
et non time.time
(et dans de nombreux cas, perf counter APIs) parce que
-
timeit
sélectionne le meilleur minuteur disponible sur votre version OS et Python. -
timeit
empêche la collecte des ordures, mais ce n'est pas quelque chose que vous voulez ou que vous ne voulez pas.
maintenant, le problème est que timeit n'est pas si simple à utiliser parce qu'il a besoin de configuration et les choses deviennent moches quand vous avez tas d'importations. Idéalement, vous voulez juste un décorateur ou utiliser with
bloc et mesurer le temps. Malheureusement, il n'y a rien intégré disponible pour cela, donc j'ai créé ci-dessous petit module utilitaire.
Module De Minuterie
# 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
Comment faire Fonctions Du Temps
Maintenant vous pouvez chronométrer n'importe quelle fonction juste en mettant un décorateur en face de lui:
import utils
@utils.MeasureTime
def MyBigFunc():
#do something time consuming
for i in range(10000):
print(i)
Comment le Temps des Blocs de Code
si vous voulez chronométrer la portion de code, mettez-la à l'intérieur du bloc 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
avantages
il y a plusieurs versions à demi-fond flottant autour de donc je tiens à souligner quelques points saillants:
- utiliser timer de timeit au lieu de temps.le temps pour les raisons décrites plus haut.
- Désactiver GC pendant le chronométrage.
- Décorateur accepte les fonctions nommé ou non params.
- possibilité de désactiver l'impression en bloc (utiliser
with utils.MeasureBlockTime() as t
puist.elapsed
). - capacité de garder le CA activé pour la synchronisation des blocs.
la seule façon dont je peux penser est d'utiliser 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)
Espère que cela va aider.