241 votes

Démarrage automatique du débogueur python en cas d'erreur

C'est une question que je me pose depuis un certain temps, mais je n'ai jamais trouvé de solution adéquate. Si j'exécute un script et que je tombe sur, disons une IndexError, python imprime la ligne, l'emplacement et une description rapide de l'erreur et sort. Est-il possible de lancer automatiquement pdb lorsqu'une erreur est rencontrée ? Je ne suis pas contre le fait d'avoir une déclaration d'importation supplémentaire en haut du fichier, ni quelques lignes de code supplémentaires.

533voto

catherine Points 964
python -m pdb -c continue myscript.py

Si vous ne fournissez pas le -c continue vous devrez alors entrer 'c' (pour Continue) lorsque l'exécution commencera. L'exécution se poursuivra alors jusqu'au point d'erreur et vous donnera le contrôle à cet endroit. Comme mentionné par eqzx ce drapeau est une nouveauté de la version 3.2 de Python. La saisie de 'c' est donc nécessaire pour les versions antérieures de Python (cf. https://docs.python.org/3/library/pdb.html ).

1 votes

Wow, merci ! Si maintenant cet appel initial de PDB pouvait aussi être évité, tout serait parfait. Des idées ?

6 votes

Merci de mentionner le " entrez 'c'. J'ai l'habitude d'entrer "r" (pour "run"), car j'y suis habitué depuis le début de l'année. gdb et lorsque vous saisissez "r" dans pdb Le programme s'exécute effectivement, mais ne s'arrête PAS (et ne génère pas de backtrace) en cas d'erreur ; j'étais perplexe jusqu'à ce que je lise ceci. Merci !

2 votes

J'ai essayé votre méthode. Mais elle ne semble pas offrir de contrôle réel comme l'inspection des variables au moment de l'erreur. La seule option qu'elle semble offrir est de redémarrer l'exécution.

146voto

Florian Bösch Points 12408

Vous pouvez utiliser traceback.print_exc pour imprimer la trace des exceptions. Utilisez ensuite sys.exc_info pour extraire le retour de trace et enfin appeler pdb.post_mortem avec cette trace

import pdb, traceback, sys

def bombs():
    a = []
    print a[0]

if __name__ == '__main__':
    try:
        bombs()
    except:
        extype, value, tb = sys.exc_info()
        traceback.print_exc()
        pdb.post_mortem(tb)

Si vous voulez lancer une ligne de commande interactive avec code.interact en utilisant les locaux de la trame d'où provient l'exception, vous pouvez faire

import traceback, sys, code

def bombs():
    a = []
    print a[0]

if __name__ == '__main__':
    try:
        bombs()
    except:
        type, value, tb = sys.exc_info()
        traceback.print_exc()
        last_frame = lambda tb=tb: last_frame(tb.tb_next) if tb.tb_next else tb
        frame = last_frame().tb_frame
        ns = dict(frame.f_globals)
        ns.update(frame.f_locals)
        code.interact(local=ns)

0 votes

La première solution est examinée plus en détail à la livre de cuisine python

4 votes

Pourquoi préférerait-on code sur pdb puisque le second semble développer le premier ?

0 votes

Je me pose la même question. Pourquoi préférez-vous code ?

73voto

tzot Points 32224

Utilisez le module suivant :

import sys

def info(type, value, tb):
    if hasattr(sys, 'ps1') or not sys.stderr.isatty():
    # we are in interactive mode or we don't have a tty-like
    # device, so we call the default hook
        sys.__excepthook__(type, value, tb)
    else:
        import traceback, pdb
        # we are NOT in interactive mode, print the exception...
        traceback.print_exception(type, value, tb)
        print
        # ...then start the debugger in post-mortem mode.
        # pdb.pm() # deprecated
        pdb.post_mortem(tb) # more "modern"

sys.excepthook = info

Nommez-le debug (ou ce que vous voulez) et mettez-le quelque part dans votre chemin python.

Maintenant, au début de votre script, ajoutez juste un import debug .

4 votes

Cela devrait être la réponse acceptée -- cela ne nécessite pas de modifier le code existant ou d'envelopper le tout dans un fichier de type try-catch ce qui est tout simplement laid IMO.

1 votes

Cela a l'air bien, mais notez que certains frameworks (par exemple flask) définissent déjà sys.excepthook . Ils ont souvent leurs propres approches encore meilleures comme werkzeug, mais voir aussi python - Flask et sys \.excepthook - Stack Overflow

57voto

Latanius Points 819

Ipython possède une commande permettant de modifier ce comportement : %pdb . Il fait exactement ce que vous avez décrit, peut-être même un peu plus (en vous donnant des backtraces plus informatifs avec coloration syntaxique et complétion de code). Il vaut vraiment la peine d'être essayé !

5 votes

Et c'est la seule réponse raisonnable à cette question.

6 votes

6 votes

Notez que -- comme également noté dans les docs que @matthiash a liés -- %debug permet d'ouvrir le débogueur après Je rencontre une erreur. Je préfère souvent cette méthode à %pdb . (Le compromis consiste simplement à taper q chaque fois que vous ne voulez pas déboguer une erreur, plutôt que de taper %debug chaque fois que vous faire voulez déboguer une erreur).

35voto

monkut Points 14549

Ce n'est pas le débogueur, mais c'est probablement aussi utile ( ?)

Je sais que j'ai entendu Guido le mentionner dans un discours quelque part.

Je viens de vérifier python - ?, et si vous utilisez la commande -i vous pouvez interagir où votre script s'est arrêté.

Donc, étant donné ce script :

testlist = [1,2,3,4,5, 0]

prev_i = None
for i in testlist:
    if not prev_i:
        prev_i = i
    else:
        result = prev_i/i

Vous pouvez obtenir ce résultat !

PS D:\> python -i debugtest.py
Traceback (most recent call last):
  File "debugtest.py", line 10, in <module>
    result = prev_i/i
ZeroDivisionError: integer division or modulo by zero
>>>
>>>
>>> prev_i
1
>>> i
0
>>>

Pour être honnête, je ne l'ai pas utilisé, mais je devrais le faire, il semble très utile.

0 votes

Léger, mais souvent juste ce qu'il faut

9 votes

Pas aussi utile, se lance dans la portée globale. On ne peut pas fouiller dans la fonction qui s'est écrasée.

0 votes

Comment faire pour que le système ne passe en mode "débogage" que s'il y a une erreur ?

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