Ce que je veux, c'est commencer à compter le temps quelque part dans mon code, puis obtenir le temps écoulé, pour mesurer le temps qu'il a fallu pour exécuter quelques fonctions. Je pense que j'utilise mal le module timeit, mais la documentation est source de confusion pour moi.
import timeit
start = timeit.timeit()
print "hello"
end = timeit.timeit()
print end - start
Si vous souhaitez simplement mesurer le temps écoulé entre deux points, vous pouvez utiliser time.time()
:
import time
start = time.time()
print("hello")
end = time.time()
print(end - start)
Cela donne le temps d'exécution en secondes.
Une autre option depuis la version 3.3 pourrait être d’utiliser perf_counter
ou process_time
, selon vos besoins. Avant la version 3.3, il était recommandé d’utiliser time.clock
(merci orange ). Cependant, il est actuellement obsolète:
Sous Unix, renvoyez le temps processeur actuel sous forme de nombre à virgule flottante exprimé en secondes. La précision, et en fait la définition même de la signification de «temps de processeur», dépend de celle de la fonction C. du même nom.
Sous Windows, cette fonction retourne les secondes de l'horloge murale écoulées depuis le premier appel à cette fonction, sous forme de nombre à virgule flottante, basé sur le Fonction Win32
QueryPerformanceCounter()
. La résolution est typiquement mieux qu'une microseconde.Déconseillé depuis la version 3.3: Le comportement de cette fonction dépend sur la plate-forme: use
perf_counter()
ouprocess_time()
à la place de, en fonction de vos exigences, avoir un comportement bien défini.
Utilisez timeit.default_timer
au lieu de timeit.timeit
. Le premier fournit automatiquement la meilleure horloge disponible sur votre plate-forme et votre version de 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 est affecté à time.time () ou time.clock () selon le système d'exploitation. Sur Python 3.3+ default_timer est time.perf_counter () sur toutes les plateformes. Voir Python - time.clock () vs time.time () - exactitude?
Voir également:
Puisque time.clock () est obsolète à partir de Python 3.3 , vous voudrez utiliser time.perf_counter()
pour le minutage global du système ou time.process_time()
pour le minutage global du processus, comme vous l'avez utilisé utiliser time.clock()
:
import time
t = time.process_time()
#do some stuff
elapsed_time = time.process_time() - t
La nouvelle fonction process_time
n'inclura pas le temps écoulé pendant le sommeil.
Étant donné une fonction que vous souhaitez chronométrer,
test.py:
def foo():
# print "hello"
return "hello"
la manière la plus simple d'utiliser timeit
est de l'appeler à partir de 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 des fonctions. Ils peuvent donner des résultats trompeurs .
PS. Ne mettez pas les déclarations d'impression dans une fonction que vous souhaitez chronométrer; sinon, le temps mesuré dépendra de la vitesse du terminal .
Je préfère ça. timeit
doc est beaucoup trop déroutant.
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))
Notez qu'il n'y a pas de formatage ici, je viens d'écrire hh:mm:ss
dans l'impression pour pouvoir interpréter time_elapsed
C'est amusant de faire cela avec un gestionnaire de contexte qui mémorise automatiquement l'heure de début lors de l'entrée dans un bloc with
, puis gèle l'heure de fin à 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 cela (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() )
Voici 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 quelques codes de démonstration exécutables:
import time
with elapsed_timer() as elapsed:
time.sleep(1)
print(elapsed())
time.sleep(2)
print(elapsed())
time.sleep(3)
Notez que, par la conception de cette fonction, la valeur de retour de elapsed()
est gelée à la sortie du bloc et que des appels ultérieurs renvoient la même durée (environ 6 secondes dans cet exemple de jouet).
L'utilisation de time.time
pour mesurer l'exécution vous donne le temps global d'exécution de vos commandes, y compris le temps d'exécution passé par d'autres processus sur votre ordinateur. C'est le moment que l'utilisateur remarque, mais ce n'est pas bien si vous voulez comparer différents extraits de code/algorithmes/fonctions/...
Plus d'informations sur timeit
:
Si vous souhaitez un aperçu plus approfondi du profilage:
Update: J'ai utilisé http://pythonhosted.org/line_profiler/ beaucoup au cours de la dernière année et le trouve très utile et recommande de l'utiliser au lieu du module de profil Pythons.
Voici une minuscule classe timer qui retourne la chaîne "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
Usage:
# 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 excellent 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, vous pouvez simplement exécuter:
python -m cProfile -o timeStats.profile timeFunctions.py
Cela consiste à utiliser le module cProfile pour profiler toutes les fonctions de timeFunctions.py et à collecter les statistiques dans le fichier timeStats.profile. Notez que nous n'avons pas eu besoin d'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 de statistiques, vous pouvez exécuter le module pstats comme suit:
python -m pstats timeStats.profile
Cela lance le navigateur de statistiques interactif qui vous donne beaucoup de fonctionnalités de Nice. Pour votre cas d'utilisation particulier, vous pouvez simplement vérifier les statistiques de votre fonction. Dans notre exemple, vérifier les statistiques des 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 factice 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 aucun de mes codes existants pour obtenir ces numéros et, évidemment, à aider au profilage.
Voici un autre gestionnaire de contexte pour le code de synchronisation -
Usage:
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 de temps
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
Utilisez le module de profileur. Cela donne un profil très détaillé.
import profile
profile.run('main()')
il sort 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.
(Avec Ipython uniquement), vous pouvez utiliser % timeit pour mesurer le temps de traitement moyen:
def foo():
print "hello"
et alors:
%timeit foo()
le résultat est quelque chose comme:
10000 loops, best of 3: 27 µs per loop
Nous sommes en 2019 maintenant. Faisons-le de manière concise:
from ttictoc import TicToc
t = TicToc() ## TicToc("name")
t.tic();
# your code ...
t.toc();
print(t.elapsed)
Avantages de l’utilisation de cette approche au lieu d’autres:
t = TicToc(nested=True)
t.tic()
some code1...
t.tic()
some code2...
t.tic()
some code3...
print(t.toc()) # Prints time for code 3
print(t.toc()) # Prints time for code 2 with code 3
print(t.toc()) # Prints time for code 1 with code 2 and 3
t = TicToc("save user")
print(t.name)
Veuillez vous référer à ceci lien pour des instructions plus détaillées.
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 à quelque chose. C’est une façon de le faire qui, à mon avis, est très 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 de Python 3 et non de Python 2.7. Cependant, cela fonctionne avec n'importe quelle autre fonction. À votre santé!
Je l'aime bien simple (python 3):
from timeit import timeit
timeit(lambda: print("hello"))
La sortie est microsecondes pour une exécution unique:
2.430883963010274
Explication: timeit exécute la fonction anonyme 1 million de fois par défaut et le résultat est donné en secondes . Par conséquent, le résultat pour 1 exécution unique est identique, mais en microsecondes en moyenne.
Pour les opérations lentes, ajoutez un nombre inférieur d'itérations, sinon vous pourriez attendre en permanence:
import time
timeit(lambda: time.sleep(1.5), number=1)
La sortie est toujours en secondes pour le nombre total d'itérations:
1.5015795179999714
Nous pouvons également convertir le temps en temps lisible par l'homme.
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')
Voici mes conclusions après avoir parcouru de nombreuses 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, des API de compteur), car
timeit
sélectionne la meilleure minuterie disponible sur votre système d'exploitation et la version Python. timeit
désactive la récupération de place, mais ce n'est pas quelque chose que vous ne voulez peut-être pas.Le problème, c’est que timeit n’est pas aussi simple à utiliser car il a besoin d’être configuré et les choses deviennent laides lorsque vous importez beaucoup. Idéalement, vous voulez juste un décorateur ou utilisez le bloc with
et mesurez le temps. Malheureusement, il n'y a rien d'intégré disponible pour cela, alors j'ai créé ci-dessous un petit module utilitaire.
Module utilitaire de synchronisation
# 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 utiliser les fonctions de temps
Maintenant, vous pouvez chronométrer n'importe quelle fonction simplement en plaçant un décorateur devant elle:
import utils
@utils.MeasureTime
def MyBigFunc():
#do something time consuming
for i in range(10000):
print(i)
Comment chronométrer les blocs
Si vous voulez chronométrer une partie du code, placez-le simplement dans le 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 existe plusieurs versions à moitié sauvegardées, je tiens donc à souligner quelques points saillants:
with utils.MeasureBlockTime() as t
, puis t.elapsed
).Une autre façon d'utiliser timeit :
from timeit import timeit
def func():
return 1 + 1
time = timeit(func, number=1)
print(time)
J'ai fait une bibliothèque pour cela, si vous voulez mesurer une fonction, vous pouvez simplement le faire comme ça
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)
%load_ext snakeviz
%%snakeviz
Cela prend juste ces 2 lignes de code dans un cahier Jupyter , et il génère un diagramme interactif de Nice. Par exemple:
Voici le code. Encore une fois, les 2 lignes commençant par %
sont les seules lignes de code supplémentaires nécessaires pour utiliser 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)
Il semble également possible de faire fonctionner snakeviz en dehors des cahiers. Plus d'infos sur le site web de snakeviz .
Vous pouvez utiliser timeit.
Voici un exemple sur la façon de tester naive_func avec un paramètre 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 la fonction wrapper si la fonction n'a aucun paramètre.
Temps de mesure en secondes:
from timeit import default_timer as timer
from datetime import timedelta
start = timer()
end = timer()
print(timedelta(seconds=end-start))
Le seul moyen auquel 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)
J'espère que ça va aider.