54 votes

Profiler en Python : Qui a appelé la fonction ?

Je fais du profilage en Python en utilisant cProfile . J'ai trouvé une fonction qui prend beaucoup de temps au CPU. Comment puis-je savoir quelle fonction appelle le plus cette fonction lourde ?

EDIT :

Je me contenterai d'une solution de contournement : Puis-je écrire une ligne Python à l'intérieur de cette fonction lourde qui imprimera le nom de la fonction qui l'a appelée ?

113voto

dbr Points 66401

Je visualise presque toujours la sortie du module cProfile en utilisant Gprof2dot En fait, il convertit la sortie en un graphe de type graphvis (a .dot ), par exemple :

example gprof2dot output

Il est ainsi très facile de déterminer quelle fonction est la plus lente, et quelle(s) fonction(s) l'a (ont) appelée(s).

L'usage est :

python -m cProfile -o output.pstats path/to/your/script arg1 arg2
gprof2dot.py -f pstats output.pstats | dot -Tpng -o output.png

8 votes

+1 C'EST F******** IMPRESSIONNANT ET ÉTONNANT ! Merci de me l'avoir montré wow

2 votes

Si vous voulez profiler une expression comme avec cProfile.run(exp), vous pouvez utiliser ceci (crée toujours un fichier pstats temporaire) : def run(exp,output="profile.png",statsFileName="stats. pstats") : import cProfile cProfile.run(exp,statsFileName) os.system("python gprof2dot.py -f pstats %s | dot -Tpng -o %s > /dev/null 2>&1" % (statsFileName, output))

0 votes

Merci. C'est aussi la façon la plus portable de le faire.

36voto

Nadia Alramli Points 40381

Cela ne répondra peut-être pas directement à votre question, mais vous aidera certainement. Si vous utilisez le profileur avec l'option --sort cumulative, il triera les fonctions par temps cumulé. Ce qui est utile pour détecter non seulement les fonctions lourdes mais aussi les fonctions qui les appellent.

python -m cProfile --sort cumulative myScript.py

Il existe une solution de contournement pour obtenir la fonction de l'appelant :

import inspect
print inspect.getframeinfo(inspect.currentframe().f_back)[2]

Vous pouvez ajouter autant de f_back que vous voulez au cas où vous voudriez que l'appelant appelle, etc. Si vous voulez calculer les appels fréquents, vous pouvez le faire :

record = {}

caller = inspect.getframeinfo(inspect.currentframe().f_back)[2]
record[caller] = record.get(caller, 0) + 1

Ensuite, imprimez-les par ordre de fréquence :

print sorted(record.items(), key=lambda a: a[1])

3 votes

Si vous enregistrez les résultats de cProfile dans un fichier et que vous utilisez la fonction pstats pour charger le profil, vous pouvez alors demander directement les appelants de la fonction lourde : loaded_stats_object.print_callers('heavy_function')

10voto

inspect.stack() vous donnera la pile de l'appelant actuel.

3voto

Anonymous Points 1568

Vous voudrez peut-être jeter un coup d'œil à pycallgraphe .

1voto

lothar Points 11904

Je n'ai pas utilisé cProfile moi-même, mais la plupart des profileurs vous donnent une hiérarchie des appels.
En cherchant sur Google, j'ai trouvé ceci diapositives sur cProfile. Cela peut aider. La page 6 semble indiquer que cProfile fournit une hiérarchie.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X