it-swarm.com.de

Python-Debugger wird bei Fehler automatisch gestartet

Ü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.

166
jeremy

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)
102
Florian Bösch
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) ).

342

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.

58
tzot

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!

33
Latanius

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.

31
monkut

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.

16
wodow

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.

5
Rory

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.

5
Jehandad

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.

3
Zlatko Karakaš

Wenn Sie ipython verwenden, geben Sie nach dem Start %pdb ein.

In [1]: %pdb
Automatic pdb calling has been turned ON
3
Willemoes

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.

2
Hannah

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.

0
dangonfast

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

0
vlad-ardelean