Mettre une série de print
dans son programme a ses limites, et python possède nativement une excellente alternative.
Pour la plupart des langages, on utilise un debugger intégré dans un IDE ou un programme à part. Ou alors on se contente de fonctions telles que var_dump
ou print_r
. En Python, on utilise le module pdb
.
Quand vous voulez savoir ce qui se passe à un endroit du programme, à la ligne précise où vous souhaitez explorer le problème, ajoutez à votre code :
import pdb; pdb.set_trace() |
Et relancez votre programme depuis une console.
L’exécution du programme va alors se figer, et dans la console vous aurez accès à un shell special:
(Pdb) |
A quoi sert pdb
Dans ce shell vous pouvez entrer deux choses:
- N’importe quelle expression Python qui tient sur une ligne.
- Des commandes
pdb
speciales.
Ce qui est génial, c’est que toute expression Python sera éxécutée dans le context de la ligne où le programme s’est arrêté.
Donc vous pouvez faire des print
, des if
, des listes en intention, bref, tous les tests que vous voulez, avec les variables du programme dans l’état où elles sont à ce moment là.
Vous avez accès à tout le code, y compris vos propres objets, classes et fonctions. En fait, vous avez même accès à l’import, et donc à toutes les librairies importables.
L’essentiel des commandes
En plus de pouvoir exécuter du Python, vous pouvez utiliser des commandes. Il y en a des nombreuses, mais vous pouvez tirer l’essentiel de pdb
avec six d’entre elles:
-
l
: Liste quelques lignes de code avant et après là où vous vous trouver. Utile pour se resituer dans le contexte du programme. ‘l’ pour ‘list’. -
n
: Exécute la ligne suivante. Vous pouvez ainsi continuer l’exécution du programme de bout en bout, ligne par ligne, et le tester en entier. ‘n’ pour ‘next’. -
s
: Si votre ligne contient un appel de fonction ou de méthode, rentre dans à l’intérieur. ‘s’ pour ‘step in’. -
r
: Si vous êtes dans une fonction ou une méthode, celà permet d’en sortir et de passer dans le scope du dessus. ‘r’ pour ‘return’. unt
: Si vous êtes à la dernière ligne d’une boucle, permet de reprendre l’exécution jusqu’à la sortie de la boucle. ‘unt’ pour ‘until’.q
: Quitte brutalement le programme en le faisant crasher. ‘q’ pour ‘quit’.c
: Quitte le debugger et continue l’exécution du programme normalement. Tous les changements que vous avez fait dans le code sont pris en compte. ‘c’ pour ‘continue’.
Pour utiliser une commande, il suffit de taper la lettre et d’appuyer sur entrée
. Si vous appuyez sur entrée
sans rien saisir, la commande précédente est exécutée, ce qui vous évitera de spammer le shell de commandes n
.
Les limites de pdb
- Les commandes ont priorité sur le code Python. Vous ne pouvez donc pas assigner des variables dont le nom est en une seul lettre. C’est ennuyeux pour accéder à la variable ‘
i
‘ dans une boucle for. Dans ce cas, prefixez ‘i
‘ par un ‘!
‘ et il sera considéré comme du Python, et non comme une commande. - Si vous mettez
set_trace
dans une boucle, le debugger va se lancer à chaque tour de boucle, ce qui embrouille tout. Dans ce cas, et dans tous les cas où vous voulez que le debugger se lance à un moment particulier, utilisez unif
ou untry/except
pour queset_trace
ne soit appelé que dans un cas précis. - Dans le cas de threads, de processus séparés, ou quand vous n’avez pas accès à
stdout
,pdb
ne peut rien pour vous. Dans ce cas, le module logging est votre ami.
pdb + ipython = ipdb
Si vous êtes fan d’ipython, un coup de pip:
pip install ipdb |
Et ensuite dans le programme:
import ipdb; ipdb.set_trace() |
Vous aurez alors accès au shell de pdb
, mais avec en prime les commandes et l’autocompletion d’ipython
Mettre un break point programmatiquement en javascript
Dans une moindre mesure, on peut aussi lancer un shell de debug depuis javascript. Ouvrez votre fenêtre d’outils Web intégrés au navigateur, Firebug ou équivalent.
Normalement il faut trouver votre script, puis la ligne, et mettre un break point.
Mais dans les navigateurs récents, vous pouvez juste ajouter:
debugger; |
A la ligne voulue, et recharger la page. Votre outil de debuggage se mettra au break point automatiquement
On en apprend tous les jours ! Merci.
Apparement
pdb
ne marche pas avec QT4, donc pour tous les amateurs de PyQT, utilisez pdb4qt.C’est une version qui réconcilie la lib avec le debugger, essentiellement en faisant un appel de
pyqtRemoveInputHook()
justeavant le set_trace()
.Quid de PySide ? Parce qu’en remontant au sujet de SO (http://stackoverflow.com/questions/1736015/debugging-a-pyqt4-app) qui est à la base de pdbqt4, il est dit que cela ne marche pas avec PySide…
Aucune idée.
je découvre pdb et vraiment ça mérite d’être connu. C’est bien plus complet que le debug avec IDLE.
Comment fait-on quand l’entrée standard (stdin) est attrapée par le processus ? (À l’aide de
tty.setcbreak(stdin.fileno())
)Pour ne rien arranger, comment fait-on quand la sortie standard est effacée régulièrement aussi ? (Avec la séquence ansi
\033[2J
)