Je veux créer une fonction python pour tester le temps passé dans chaque fonction et afficher son nom avec son heure. Comment puis-je imprimer le nom de la fonction et s'il existe un autre moyen de le faire?
def measureTime(a):
start = time.clock()
a()
elapsed = time.clock()
elapsed = elapsed - start
print "Time spent in (function name) is: ", elapsed
D'abord et avant tout, je suggère fortement d'utiliser un profileur ou au moins une utilisation timeit .
Cependant, si vous voulez écrire votre propre méthode de chronométrage pour apprendre, voici un endroit pour commencer à utiliser un décorateur.
Python 2:
def timing(f):
def wrap(*args):
time1 = time.time()
ret = f(*args)
time2 = time.time()
print '%s function took %0.3f ms' % (f.func_name, (time2-time1)*1000.0)
return ret
return wrap
Et l'utilisation est très simple, utilisez simplement le décorateur @timing:
@timing
def do_work():
#code
Python 3:
def timing(f):
def wrap(*args):
time1 = time.time()
ret = f(*args)
time2 = time.time()
print('{:s} function took {:.3f} ms'.format(f.__name__, (time2-time1)*1000.0))
return ret
return wrap
Remarque J'appelle f.func_name
pour obtenir le nom de la fonction sous forme de chaîne (dans Python 2) ou f.__name__
dans Python 3.
Après avoir joué avec le module timeit
, je n’aime pas son interface, qui n’est pas aussi élégante que les deux méthodes suivantes.
Le code suivant est dans Python 3.
C'est presque la même chose avec la méthode de @ Mike. Ici, j'ajoute kwargs
et functools
wrap pour le rendre meilleur.
def timeit(func):
@functools.wraps(func)
def newfunc(*args, **kwargs):
startTime = time.time()
func(*args, **kwargs)
elapsedTime = time.time() - startTime
print('function [{}] finished in {} ms'.format(
func.__name__, int(elapsedTime * 1000)))
return newfunc
@timeit
def foobar():
mike = Person()
mike.think(30)
from contextlib import contextmanager
@contextmanager
def timeit_context(name):
startTime = time.time()
yield
elapsedTime = time.time() - startTime
print('[{}] finished in {} ms'.format(name, int(elapsedTime * 1000)))
Par exemple, vous pouvez l'utiliser comme:
with timeit_context('My profiling code'):
mike = Person()
mike.think()
Et le code dans le bloc with
sera chronométré.
En utilisant la première méthode, vous pouvez commenter facilement le décorateur pour obtenir le code normal. Cependant, il ne peut chronométrer qu'une fonction. Si vous avez une partie du code que vous ne voulez pas quoi en faire une fonction, alors vous pouvez choisir la deuxième méthode.
Par exemple, maintenant vous avez
images = get_images()
bigImage = ImagePacker.pack(images, width=4096)
drawer.draw(bigImage)
Maintenant, vous voulez chronométrer la ligne bigImage = ...
. Si vous le changez en fonction, ce sera:
images = get_images()
bitImage = None
@timeit
def foobar():
nonlocal bigImage
bigImage = ImagePacker.pack(images, width=4096)
drawer.draw(bigImage)
Ça n'a pas l'air génial ... Et si vous êtes dans Python 2, qui n'a pas de mot clé nonlocal
.
Au lieu de cela, l’utilisation de la deuxième méthode est très bien adaptée ici:
images = get_images()
with timeit_context('foobar'):
bigImage = ImagePacker.pack(images, width=4096)
drawer.draw(bigImage)
Je ne vois pas quel est le problème avec le module timeit
. C'est probablement la manière la plus simple de le faire.
import timeit
timeit.timeit(a, number=1)
Il est également possible d'envoyer des arguments aux fonctions. Tout ce dont vous avez besoin est d’envelopper votre fonction en utilisant des décorateurs. Plus d'explications ici: http://www.pythoncentral.io/time-a-python-function/
Le seul cas où vous voudriez peut-être écrire vos propres déclarations de minutage est si vous voulez exécuter une fonction une seule fois et souhaitez également obtenir sa valeur de retour.
L'avantage d'utiliser le module timeit
est qu'il vous permet de répéter le nombre d'exécutions. Cela peut être nécessaire car d’autres processus risquent d’interférer avec la précision de votre minutage. Donc, vous devriez l'exécuter plusieurs fois et regarder la valeur la plus basse.
Timeit a deux gros défauts: il ne renvoie pas la valeur de retour de la fonction et utilise eval, ce qui nécessite de transmettre un code de configuration supplémentaire pour les importations. Cela résout les problèmes de manière simple et élégante:
def timed(f):
start = time.time()
ret = f()
elapsed = time.time() - start
return ret, elapsed
timed(lambda: database.foo.execute('select count(*) from source.apachelog'))
(<sqlalchemy.engine.result.ResultProxy object at 0x7fd6c20fc690>, 4.07547402381897)
Méthode Decorator utilisant la bibliothèque decorator Python:
import decorator
@decorator
def timing(func, *args, **kwargs):
'''Function timing wrapper
Example of using:
``@timing()``
'''
fn = '%s.%s' % (func.__module__, func.__name__)
timer = Timer()
with timer:
ret = func(*args, **kwargs)
log.info(u'%s - %0.3f sec' % (fn, timer.duration_in_seconds()))
return ret
Voir l'article sur mon blog:
Il existe un outil simple pour le timing. https://github.com/RalphMao/PyTimer
Cela peut fonctionner comme un décorateur :
from pytimer import Timer
@Timer(average=False)
def matmul(a,b, times=100):
for i in range(times):
np.dot(a,b)
Sortie:
matmul:0.368434
matmul:2.839355
Il peut également fonctionner comme un minuteur de plug-in avec un contrôle d'espace de nom (utile si vous l'insérez dans une fonction comportant beaucoup de codes et pouvant être appelé n'importe où ailleurs).
timer = Timer()
def any_function():
timer.start()
for i in range(10):
timer.reset()
np.dot(np.ones((100,1000)), np.zeros((1000,500)))
timer.checkpoint('block1')
np.dot(np.ones((100,1000)), np.zeros((1000,500)))
np.dot(np.ones((100,1000)), np.zeros((1000,500)))
timer.checkpoint('block2')
np.dot(np.ones((100,1000)), np.zeros((1000,1000)))
for j in range(20):
np.dot(np.ones((100,1000)), np.zeros((1000,500)))
timer.summary()
for i in range(2):
any_function()
Sortie:
========Timing Summary of Default Timer========
block2:0.065062
block1:0.032529
========Timing Summary of Default Timer========
block2:0.065838
block1:0.032891
J'espère que ça va aider
Ma façon de le faire:
from time import time
def printTime(start):
end = time()
duration = end - start
if duration < 60:
return "used: " + str(round(duration, 2)) + "s."
else:
mins = int(duration / 60)
secs = round(duration % 60, 2)
if mins < 60:
return "used: " + str(mins) + "m " + str(secs) + "s."
else:
hours = int(duration / 3600)
mins = mins % 60
return "used: " + str(hours) + "h " + str(mins) + "m " + str(secs) + "s."
Définissez une variable comme start = time()
avant d'exécuter la/les boucle (s), et printTime(start)
juste après le bloc.
et vous avez la réponse.