C’est une question à laquelle je me pose des questions depuis un certain temps, mais je n’ai jamais trouvé de solution adéquate. Si je lance un script et que je rencontre, par exemple, une erreur IndexError, python imprime la ligne, l'emplacement et la description rapide de l'erreur, puis se termine. Est-il possible de démarrer 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.
Vous pouvez utiliser traceback.print_exc pour imprimer le suivi des exceptions. Ensuite, utilisez sys.exc_info pour extraire la trace et enfin appeler pdb.post_mortem avec cette trace
import pdb, traceback, sys
def bombs():
a = []
print a[0]
if __== '__main__':
try:
bombs()
except:
extype, value, tb = sys.exc_info()
traceback.print_exc()
pdb.post_mortem(tb)
Si vous souhaitez démarrer une ligne de commande interactive avec code.interact en utilisant les paramètres locaux du cadre d'où provient l'exception, vous pouvez le faire.
import traceback, sys, code
def bombs():
a = []
print a[0]
if __== '__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)
python -m pdb -c continue myscript.py
Si vous ne fournissez pas l'indicateur -c continue
, vous devrez entrer «c» (pour continuer) au début de l'exécution. Ensuite, il fonctionnera jusqu'au point d'erreur et vous donnera le contrôle là-bas. Comme mentionné par eqzx , ce drapeau est un nouvel ajout dans python 3.2, il est donc nécessaire de saisir 'c' pour les versions antérieures de Python (voir https://docs.python.org/3/library/pdb.html ).
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 préférez) et mettez-le quelque part dans votre chemin python.
Maintenant, au début de votre script, ajoutez simplement un import debug
.
Ipython a une commande permettant de basculer ce comportement:% pdb . Il fait exactement ce que vous avez décrit, peut-être même un peu plus (en vous donnant des traces plus informatives avec la coloration syntaxique et l’achèvement du code). Cela vaut vraiment la peine d'essayer!
Ce n'est pas le débogueur, mais probablement tout aussi utile (?)
Je sais que j'ai entendu Guido en parler dans un discours quelque part.
Je viens de vérifier python - ?, et si vous utilisez la commande -i, vous pouvez interagir là 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 cette sortie!
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 l'être, semble très utile.
IPython rend cela simple en ligne de commande:
python myscript.py arg1 arg2
peut être réécrit pour
ipython --pdb myscript.py -- arg1 arg2
Ou, de la même manière, si vous appelez un module:
python -m mymodule arg1 arg2
peut être réécrit pour
ipython --pdb -m mymodule -- arg1 arg2
Notez le --
pour empêcher IPython de lire les arguments du script comme étant les siens.
Cela présente également l’avantage d’appeler le débogueur IPython amélioré (ipdb) au lieu de pdb.
Vous pouvez mettre cette ligne dans votre code:
import pdb ; pdb.set_trace()
Plus d'infos: Démarrer le débogueur python à n’importe quelle ligne
Si vous utilisez l'environnement IPython, vous pouvez simplement utiliser% debug et le shell vous ramènera à la ligne incriminée avec l'environnement ipdb pour les inspections, etc. le même.
Pour le faire fonctionner sans avoir à taper c au début, utilisez:
python -m pdb -c c <script name>
Pdb a ses propres arguments en ligne de commande: -c c exécutera la commande c(ontinue) au début de l'exécution et le programme s'exécutera sans interruption jusqu'à l'erreur.
Si vous utilisez ipython
, après avoir lancé %pdb
In [1]: %pdb
Automatic pdb calling has been turned ON
python -m pdb script.py dans python2.7 appuyez sur continuer pour démarrer et l'erreur sera exécutée pour pouvoir déboguer.
Si vous utilisez un module:
python -m mymodule
Et maintenant, vous voulez entrer pdb
lorsqu'une exception se produit, procédez comme suit:
PYTHONPATH="." python -m pdb -c c mymodule/__main__.py
(ou expand your PYTHONPATH
). La PYTHONPATH
est nécessaire pour que le module soit trouvé dans le chemin, puisque vous exécutez maintenant le module pdb
.
Placez un point d'arrêt à l'intérieur du constructeur de la classe d'exception la plus haute de la hiérarchie et la plupart du temps, vous verrez où l'erreur a été générée.
Mettre un point d'arrêt signifie ce que vous voulez dire: vous pouvez utiliser un IDE, un pdb.set_trace
ou autre chose