J'ai cette application Python qui se bloque de temps en temps et je ne peux pas savoir où.
Existe-t-il un moyen de signaler à l'interpréteur Python de vous montrer le code exact en cours d'exécution?
Une sorte de stacktrace à la volée?
Questions connexes:
Réponses:
J'ai un module que j'utilise pour des situations comme celle-ci - où un processus s'exécutera pendant une longue période mais se bloquera parfois pour des raisons inconnues et irréprochables. C'est un peu hacky, et ne fonctionne que sur unix (nécessite des signaux):
Pour l'utiliser, il suffit d'appeler la fonction listen () à un moment donné au démarrage de votre programme (vous pouvez même la coller dans site.py pour que tous les programmes python l'utilisent), et laissez-la s'exécuter. À tout moment, envoyez au processus un signal SIGUSR1, en utilisant kill ou en python:
Cela provoquera la rupture du programme sur une console python au point où il se trouve actuellement, vous montrant la trace de la pile et vous permettant de manipuler les variables. Utilisez control-d (EOF) pour continuer à fonctionner (mais notez que vous interromprez probablement toutes les E / S, etc. au point que vous signalez, donc ce n'est pas totalement non intrusif.
J'ai un autre script qui fait la même chose, sauf qu'il communique avec le processus en cours via un canal (pour permettre le débogage des processus en arrière-plan, etc.). C'est un peu grand pour poster ici, mais je l'ai ajouté comme recette de livre de recettes en python .
la source
faulthandler
module (et son backport trouvé sur PyPI) pour un gestionnaire de signal de niveau C qui imprimera la pile Python sans exiger que la boucle d'interpréteur soit réactive.La suggestion d'installer un gestionnaire de signaux est bonne et je l'utilise beaucoup. Par exemple, bzr installe par défaut un gestionnaire SIGQUIT qui invoque
pdb.set_trace()
pour vous déposer immédiatement dans une invite pdb . (Voir la source du module bzrlib.breakin pour les détails exacts.) Avec pdb, vous pouvez non seulement obtenir la trace de la pile actuelle mais également inspecter les variables, etc.Cependant, j'ai parfois besoin de déboguer un processus dans lequel je n'avais pas la prévoyance d'installer le gestionnaire de signaux. Sur Linux, vous pouvez attacher gdb au processus et obtenir une trace de pile python avec certaines macros gdb. Mettez http://svn.python.org/projects/python/trunk/Misc/gdbinit dans
~/.gdbinit
, puis:gdb -p
PID
pystack
Ce n'est malheureusement pas totalement fiable, mais cela fonctionne la plupart du temps.
Enfin, l'attachement
strace
peut souvent vous donner une bonne idée de ce que fait un processus.la source
python-dbg
). Sans ces symboles, vous ne semblez pas obtenir beaucoup d'informations utiles.Unable to locate python frame
à chaque commandeJ'ai presque toujours affaire à plusieurs threads et le thread principal ne fait généralement pas grand-chose, donc ce qui est le plus intéressant est de vider toutes les piles (ce qui ressemble plus au dump de Java). Voici une implémentation basée sur ce blog :
la source
Obtenir une trace de pile d'un programme python non préparé , s'exécuter dans un python stock sans symboles de débogage peut être fait avec pyrasite . Fonctionné comme un charme pour moi sur Ubuntu Trusty:
(Pointe du chapeau à @Albert, dont la réponse contenait un pointeur vers cela, entre autres outils.)
la source
dump_stacks.py
était tout simplementimport traceback; traceback.print_stack()
traceback -l
vous donne une liste de scripts python prédéfinis que vous pouvez utiliser et endump_stacks.py
fait partie. Si vous utilisez le vôtre (par exemple pour écrire la trace de la pile dans un fichier), il peut être judicieux d'utiliser un nom différent.apt-get install gdb python-dbg
Conseil important: exécutez (ou équivalent) avant d'exécuter la pyrasite, sinon elle échouera silencieusement. Fonctionne comme un charme sinon!Vous pouvez également bien formater la trace de la pile, voir la documentation .
Edit : Pour simuler le comportement de Java, comme suggéré par @Douglas Leeder, ajoutez ceci:
au code de démarrage de votre application. Ensuite, vous pouvez imprimer la pile en l'envoyant
SIGUSR1
au processus Python en cours d'exécution.la source
Le module traceback a de belles fonctions, parmi lesquelles: print_stack:
la source
import traceback; f = open('/tmp/stack-trace.log', 'w') traceback.print_stack(file=f) f.close()
Vous pouvez essayer le module de traitement des erreurs . Installez-le en utilisant
pip install faulthandler
et ajoutez:au début de votre programme. Envoyez ensuite SIGUSR1 à votre processus (ex:) pour
kill -USR1 42
afficher le traceback Python de tous les threads vers la sortie standard. Lisez la documentation pour plus d'options (ex: connectez-vous dans un fichier) et d'autres façons d'afficher la trace.Le module fait maintenant partie de Python 3.3. Pour Python 2, voir http://faulthandler.readthedocs.org/
la source
Ce qui m'a vraiment aidé ici, c'est le conseil de spiv (que je voterais et commenterais si j'avais les points de réputation) pour obtenir une trace de pile d'un processus Python non préparé . Sauf que cela n'a pas fonctionné jusqu'à ce que je modifie le script gdbinit . Alors:
téléchargez http://svn.python.org/projects/python/trunk/Misc/gdbinit et placez-le dans
~/.gdbinit
éditez-le, changez[modifier: plus nécessaire; le fichier lié a déjà cette modification au 14/01/2010]PyEval_EvalFrame
enPyEval_EvalFrameEx
Attachez gdb:
gdb -p PID
Obtenez la trace de la pile python:
pystack
la source
No symbol "co" in current context.
J'ajouterais ceci en tant que commentaire à la réponse de haridsv , mais je n'ai pas la réputation de le faire:
Certains d'entre nous sont toujours bloqués sur une version de Python antérieure à 2.6 (requise pour Thread.ident), j'ai donc fait fonctionner le code dans Python 2.5 (mais sans que le nom du thread soit affiché) en tant que tel:
la source
python -dv yourscript.py
Cela fera exécuter l'interpréteur en mode débogage et vous donnera une trace de ce que fait l'interpréteur.
Si vous souhaitez déboguer le code de manière interactive, vous devez l'exécuter comme ceci:
python -m pdb yourscript.py
Cela dit à l'interpréteur python d'exécuter votre script avec le module "pdb" qui est le débogueur python, si vous l'exécutez comme ça, l'interpréteur sera exécuté en mode interactif, un peu comme GDB
la source
Jetez un œil au
faulthandler
module, nouveau dans Python 3.3. Unfaulthandler
backport à utiliser dans Python 2 est disponible sur PyPI.la source
Sous Solaris, vous pouvez utiliser pstack (1) Aucune modification du code python n'est nécessaire. par exemple.
la source
pstack
qui fait la même choseSi vous êtes sur un système Linux, utilisez l'extraordinaire
gdb
avec les extensions de débogage Python (peut être danspython-dbg
oupython-debuginfo
package). Il aide également avec les applications multithread, les applications GUI et les modules C.Exécutez votre programme avec:
Cela demande
gdb
de le préparerpython <programname>.py <arguments>
et de ler
défaire.Maintenant, lorsque vous programmez se bloque, basculez dans la
gdb
console, appuyez sur Ctr+Cet exécutez:Voir l' exemple de session et plus d'informations ici et ici .
la source
Je cherchais depuis un moment une solution pour déboguer mes threads et je l'ai trouvée ici grâce à haridsv. J'utilise une version légèrement simplifiée utilisant la traceback.print_stack ():
Pour mes besoins, je filtre également les threads par nom.
la source
Il vaut la peine de regarder Pydb , "une version étendue du débogueur Python vaguement basée sur le jeu de commandes gdb". Il comprend des gestionnaires de signaux qui peuvent prendre soin de démarrer le débogueur lorsqu'un signal spécifié est envoyé.
Un projet Summer of Code 2006 a cherché à ajouter des fonctionnalités de débogage à distance à pydb dans un module appelé mpdb .
la source
J'ai piraté un outil qui s'attache à un processus Python en cours d'exécution et injecte du code pour obtenir un shell Python.
Voir ici: https://github.com/albertz/pydbattach
la source
pyrasite
a parfaitement fonctionné!Cela peut être fait avec un excellent py-spy . Il s'agit d' un profileur d'échantillonnage pour les programmes Python , son travail consiste donc à s'attacher à un processus Python et à échantillonner leurs piles d'appels. Par conséquent, il
py-spy dump --pid $SOME_PID
vous suffit de vider les piles d'appels de tous les threads du$SOME_PID
processus. En règle générale, il a besoin de privilèges élevés (pour lire la mémoire du processus cible).Voici un exemple de l'apparence d'une application Python filetée.
la source
pyringe est un débogueur qui peut interagir avec les processus python en cours d'exécution, imprimer les traces de pile, les variables, etc. sans aucune configuration a priori.
Bien que j'aie souvent utilisé la solution du gestionnaire de signaux dans le passé, il peut souvent être difficile de reproduire le problème dans certains environnements.
la source
pyrasite
fonctionné comme un charme pour moi.Il n'y a aucun moyen de se connecter à un processus Python en cours d'exécution et d'obtenir des résultats raisonnables. Ce que je fais si les processus se bloquent, c'est d'accrocher Strace et d'essayer de comprendre ce qui se passe exactement.
Malheureusement, souvent, Strace est l'observateur qui "fixe" les conditions de concurrence de sorte que la sortie est également inutile.
la source
Vous pouvez utiliser PuDB , un débogueur Python avec une interface curses pour ce faire. Il suffit d'ajouter
à votre code et utilisez Ctrl-C lorsque vous souhaitez casser. Vous pouvez continuer
c
et interrompre à plusieurs reprises si vous le manquez et que vous souhaitez réessayer.la source
Je suis dans le camp GDB avec les extensions python. Suivez https://wiki.python.org/moin/DebuggingWithGdb , ce qui signifie
dnf install gdb python-debuginfo
ousudo apt-get install gdb python2.7-dbg
gdb python <pid of running process>
py-bt
Considérez également
info threads
etthread apply all py-bt
.la source
Traceback (most recent call first): Python Exception <class 'gdb.error'> No frame is currently selected.: Error occurred in Python command: No frame is currently selected.
lors de l' exécutionpy-bt
engdb
?sudo
. j'avais aussi besoin de courir engdb pyton <pid>
tant que sudo.Comment déboguer n'importe quelle fonction dans la console :
Créez une fonction où vous utilisez pdb.set_trace () , puis la fonction que vous souhaitez déboguer.
Appelez ensuite la fonction créée:
Bon débogage :)
la source
Je ne connais rien de similaire à la réponse de Java à SIGQUIT , vous devrez donc peut-être l' intégrer à votre application. Peut-être pourriez-vous créer un serveur dans un autre thread qui peut obtenir une trace de pile en réponse à un message quelconque?
la source
utilisez le module d'inspection.
stack (context = 1) Retourne une liste d'enregistrements pour la pile au-dessus de la trame de l'appelant.
Je trouve cela très utile en effet.
la source
En Python 3, pdb installera automatiquement un gestionnaire de signal la première fois que vous utiliserez c (ont (inue)) dans le débogueur. En appuyant sur Control-C par la suite, vous vous replongerez dedans. En Python 2, voici un one-liner qui devrait fonctionner même dans des versions relativement anciennes (testé en 2.7 mais j'ai vérifié la source Python en 2.4 et ça avait l'air correct):
pdb vaut la peine d'être appris si vous passez du temps à déboguer Python. L'interface est un peu obtuse mais devrait être familière à tous ceux qui ont utilisé des outils similaires, tels que gdb.
la source
Si vous devez le faire avec uWSGI, il a Python Tracebacker intégré et il suffit de l'activer dans la configuration (le numéro est attaché au nom de chaque travailleur):
Une fois que vous avez fait cela, vous pouvez imprimer le backtrace simplement en vous connectant au socket:
la source
Au moment où le code est exécuté, vous pouvez insérer ce petit extrait pour voir une trace de pile imprimée bien formatée. Il suppose que vous avez un dossier appelé
logs
dans le répertoire racine de votre projet.la source