Lancer pdb dès qu’une exception a lieu


Vous vous souvenez de excepthook et de pdb ?

Mélangeons les deux !

 
import sys
import traceback
import pdb
 
def pdb_post_mortem(exc_type, exc_val, exc_tb):
    # On affiche l'exception histoire de savoir ce qu'on debug
    print("".join(traceback.format_exception(exc_type, exc_val, exc_tb)))
    # On balance pdb en mode post mortem, c'est à dire qu'il va se lancer
    # malgré le fait que le programme ne marche plus, donnant accès
    # au contexte qu'il y avait juste avant que ça foire
    pdb.post_mortem(exc_tb)
 
# On dit à python de lancer cette fonction quand il plante
sys.excepthook = pdb_post_mortem
 
# On fait planter Python histoire de voir que ça marche bien
 
def boom():
    a = 1
    b = a / 0
boom()

Et si quand ça plante, Python nous pond la stack trace, puis nous lance un joli prompt de debugging qui donne accès à ce qu’on avait en mémoire just avant que la VM ne décède :

Traceback (most recent call last):
  File "test.py", line 16, in 
    boom()
  File "test.py", line 14, in boom
    b = a / 0
ZeroDivisionError: integer division or modulo by zero

> /home/sam/Bureau/test.py(14)test()
-> a = 1 / 0
(Pdb) 1
(Pdb) print a
1

C’est plus ou moins l’équivalent de lancer son programme manuellement avec :

python -m pdb programme.py

L’avantage de la première forme, c’est qu’on peut le setter et l’oublier, on faire une config un peu plus custom. L’avantage de la deuxième forme, c’est que c’est juste une ligne à taper, et en prime si on fait c, le programme redémarre automatiquement.

9 thoughts on “Lancer pdb dès qu’une exception a lieu

  • floweb

    On pourrait coupler ça avec Django d’après vous ?

    Je suis pas assez spécialiste pour imaginer un truc comme ça, mais y’a moyen que ce soit faisable non ?

    Werkzeug permet un truc comme ça out-of-the-box je crois, moi qui suit habitué à Flask en tout cas j’ai ça.

    Mais Django pèche de ce côté là, et ça manque quand même.

  • Sam Post author

    On peut bien entendu intégrer cette astuce à django en mettant dans le fichier settings.py :

    if DEBUG:
        # le code ici
    

    Mais Django permet d’intégrer werkzeug avec l’app django-extensions qui fournit la commande runserver_plus: on obtient exactement la même chose qu’avec flask.

  • LBarret

    ( Ne marche pas avec Pyside AFAICT, dans ce cas, il faut remplacer les exceptions dans les builtins )

  • floweb

    MERCI SAM ! <3

    Grâce à runserver_plus, je retrouve mon Werkzeug avec Django <3

Comments are closed.

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.