Über diese Frage habe ich mich schon lange gewundert, aber ich habe noch nie eine passende Lösung gefunden. Wenn ich ein Skript starte und auf etwas stoße, sagen wir zum Beispiel einen IndexError, druckt Python die Zeile, den Ort und eine schnelle Beschreibung des Fehlers und beendet das Programm. Kann pdb automatisch gestartet werden, wenn ein Fehler auftritt? Ich bin nicht gegen eine zusätzliche Importanweisung am Anfang der Datei oder ein paar zusätzliche Codezeilen.
Sie können traceback.print_exc verwenden, um den Traceback der Ausnahmen zu drucken. Verwenden Sie dann sys.exc_info , um das Traceback zu extrahieren, und rufen Sie schließlich pdb.post_mortem mit diesem Traceback auf
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)
Wenn Sie eine interaktive Befehlszeile mit code.interact starten möchten, verwenden Sie die lokalen Zeichen des Frames, von dem die Ausnahme stammt
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
Wenn Sie das Flag -c continue
nicht angeben, müssen Sie zu Beginn der Ausführung 'c' (für Fortfahren) eingeben. Dann wird es zum Fehlerpunkt laufen und Ihnen die Kontrolle geben. Wie von eqzx erwähnt, ist dieses Flag ein neuer Zusatz in Python 3.2. Daher ist die Eingabe von 'c' für frühere Python-Versionen erforderlich (siehe https://docs.python.org/3/library/pdb.html) ).
Verwenden Sie das folgende Modul:
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
Nennen Sie es debug
(oder was immer Sie möchten) und legen Sie es irgendwo in Ihren Python-Pfad.
Fügen Sie am Anfang Ihres Skripts einfach einen import debug
hinzu.
Ipython hat einen Befehl zum Umschalten dieses Verhaltens:% pdb . Es macht genau das, was Sie beschrieben haben, vielleicht sogar etwas mehr (Sie erhalten informativere Backtraces mit Syntaxhervorhebung und Code-Vervollständigung). Es ist auf jeden Fall einen Versuch wert!
Dies ist nicht der Debugger, aber wahrscheinlich genauso nützlich (?)
Ich weiß, ich habe gehört, dass Guido dies irgendwo in einer Rede erwähnt hat.
Ich habe gerade Python -? Überprüft. Wenn Sie den Befehl -i verwenden, können Sie dort interagieren, wo Ihr Skript angehalten hat.
So gegeben dieses Skript:
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
Sie können diese Ausgabe erhalten!
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
>>>
Um ehrlich zu sein, habe ich das nicht benutzt, aber ich sollte es sehr nützlich sein.
IPython macht dies in der Befehlszeile einfach:
python myscript.py arg1 arg2
kann umgeschrieben werden
ipython --pdb myscript.py -- arg1 arg2
Oder ähnlich, wenn Sie ein Modul aufrufen:
python -m mymodule arg1 arg2
kann umgeschrieben werden
ipython --pdb -m mymodule -- arg1 arg2
Beachten Sie das --
, um zu verhindern, dass IPython die Argumente des Skripts als seine eigenen liest.
Dies hat auch den Vorteil, dass der erweiterte IPython-Debugger (ipdb) anstelle von pdb aufgerufen wird.
Sie können diese Zeile in Ihren Code einfügen:
import pdb ; pdb.set_trace()
Weitere Informationen: Starten Sie den Python-Debugger in einer beliebigen Zeile.
Wenn Sie die IPython-Umgebung verwenden, können Sie einfach den% -Debug verwenden, und die Shell bringt Sie zurück zur fehlerhaften Zeile der ipdb-Umgebung für Inspektionen usw. Eine weitere Option, wie oben erwähnt, ist die Verwendung der iPython-Magie% pdb, die dies tatsächlich tut das Gleiche.
Um es laufen zu lassen, ohne am Anfang c eingeben zu müssen, verwenden Sie:
python -m pdb -c c <script name>
Pdb hat eigene Befehlszeilenargumente: -c c führt den Befehl c(ontinue) beim Start der Ausführung aus und das Programm wird bis zum Fehler ununterbrochen ausgeführt.
Wenn Sie ipython
verwenden, geben Sie nach dem Start %pdb
ein.
In [1]: %pdb
Automatic pdb calling has been turned ON
python -m pdb script.py In python2.7 drücken Sie weiter, um zu starten, und es wird der Fehler ausgeführt und dort zum Debuggen unterbrochen.
Wenn Sie ein Modul betreiben:
python -m mymodule
Und jetzt möchten Sie pdb
eingeben, wenn eine Ausnahmebedingung auftritt:
PYTHONPATH="." python -m pdb -c c mymodule/__main__.py
(oder erweitern Ihre PYTHONPATH
). Die Variable PYTHONPATH
wird benötigt, damit das Modul im Pfad gefunden wird, da Sie jetzt das Modul pdb
ausführen.
Fügen Sie einen Haltepunkt in den Konstruktor der obersten Ausnahmeklasse in der Hierarchie ein. Meistens sehen Sie, wo der Fehler aufgetreten ist.
Wenn Sie einen Haltepunkt setzen, bedeutet das, was Sie wollen: Sie können eine IDE oder pdb.set_trace
oder was auch immer verwenden