Nach dem, was ich gelesen habe, gibt es zwei Möglichkeiten, Code in Python zu debuggen:
Mit einem traditionellen Debugger wie
pdb
oderipdb
. Dies unterstützt Befehle wiec
forcontinue
,n
forstep-over
,s
forstep-into
usw.), Sie haben jedoch keinen direkten Zugriff auf eine IPython-Shell, die für die Objektprüfung äußerst nützlich sein kann.Verwenden von IPython durch Einbetten einer IPython-Shell in Ihren Code. Sie können dies tun
from ipython import embed
und dannembed()
in Ihrem Code verwenden. Wenn Ihr Programm / Skript eineembed()
Anweisung trifft , werden Sie in eine IPython-Shell verschoben. Dies ermöglicht die vollständige Überprüfung von Objekten und das Testen von Python-Code unter Verwendung aller IPython-Extras. Bei Verwendung könnenembed()
Sie den Code jedoch nicht mehr Schritt für Schritt mit praktischen Tastaturkürzeln durchlaufen.
Gibt es eine Möglichkeit, das Beste aus beiden Welten zu kombinieren? Dh
- Die Lage sein, Schritt- für -Schritt durch den Code mit praktischen PDB / IPDB Tastenkombinationen.
- Haben Sie bei einem solchen Schritt (z. B. bei einer bestimmten Anweisung) Zugriff auf eine vollwertige IPython-Shell .
IPython-Debugging wie in MATLAB:
Ein Beispiel für diese Art des "erweiterten Debuggens" finden Sie in MATLAB, wo der Benutzer immer vollen Zugriff auf die MATLAB-Engine / -Shell hat und dennoch Schritt für Schritt durch ihren Code gehen, bedingte Haltepunkte definieren usw. Von Was ich mit anderen Benutzern besprochen habe, ist die Debugging-Funktion, die die Leute am meisten vermissen, wenn sie von MATLAB zu IPython wechseln.
IPython-Debugging in Emacs und anderen Editoren:
Ich möchte die Frage nicht zu spezifisch machen, aber ich arbeite hauptsächlich in Emacs, daher frage ich mich, ob es eine Möglichkeit gibt, diese Funktionalität in sie zu integrieren. Im Idealfall ermöglicht Emacs (oder der Editor) dem Programmierer, Haltepunkte an einer beliebigen Stelle im Code festzulegen und mit dem Interpreter oder Debugger zu kommunizieren, damit dieser an dem Ort Ihrer Wahl stoppt und zu einem vollständigen IPython-Interpreter an diesem Ort gebracht wird.
!
Befehl, der jeden Python-Befehl am Haltepunkt ausführtAntworten:
Sie können die
%pdb
Magie von IPython verwenden . Rufen Sie einfach%pdb
IPython auf und wenn ein Fehler auftritt, werden Sie automatisch zu weitergeleitetipdb
. Während Sie nicht sofort den Schritt haben, sind Sieipdb
danach drin.Dies erleichtert das Debuggen einzelner Funktionen, da Sie einfach eine Datei mit laden
%load
und dann eine Funktion ausführen können. Sie könnten einen Fehler mit einemassert
an der richtigen Position erzwingen .%pdb
ist eine Linienmagie. Nennen Sie es , wie%pdb on
,%pdb 1
,%pdb off
oder%pdb 0
. Wenn es ohne Argument aufgerufen wird, funktioniert es als Umschalter.quelle
ipython --pdb file.py -- args
und werden in einer Ausnahme auf ipdb abgelegt. Könnte es wert sein, die Antwort zu ergänzen.Was ist mit ipdb.set_trace ()? In Ihrem Code:
import ipdb; ipdb.set_trace()
Update : Jetzt können wir in Python 3.7 schreiben
breakpoint()
. Es funktioniert genauso, aber es gehorcht auch derPYTHONBREAKPOINT
Umgebungsvariablen. Diese Funktion stammt aus diesem PEP .Dies ermöglicht eine vollständige Überprüfung Ihres Codes und Sie haben Zugriff auf Befehle wie
c
(Weiter),n
(Nächste Zeile ausführen),s
(Schritt in die Methode an Punkt) und so weiter.Siehe das ipdb-Repo und eine Liste der Befehle . IPython heißt jetzt Jupyter (bearbeiten: Teil von) .
ps: Beachten Sie, dass ein ipdb-Befehl Vorrang vor Python-Code hat. Um zu schreiben
list(foo)
, brauchst du alsoprint list(foo)
.Wenn Ihnen die ipython-Eingabeaufforderung gefällt (Emacs und Vim-Modi, Verlauf, Vervollständigungen usw.), ist es auch einfach, dasselbe für Ihr Projekt zu erhalten, da es auf dem Python-Eingabeaufforderungs-Toolkit basiert .
quelle
ipdb
in EmacsRealGUD
undisend-mode
genau das zu tun , was der OP fragt.breakpoint()
ist wunderbar. In PyCharm werden Sie sogar in den PyCharm-Debugger versetzt. Es ist auch eine schnelle Möglichkeit, den PyCharm-Debugger über Funktionen aufzurufen, die in die Konsole eingefügt wurden.(Update am 28. Mai 2016) Verwenden von RealGUD in Emacs
Für jeden in Emacs zeigt dieser Thread , wie man alles erreicht, was im OP (und mehr) beschrieben ist
ipdb
) betrieben werden kann.isend-mode
.Die Kombination dieser beiden Pakete ist äußerst leistungsfähig und ermöglicht es, genau das im OP beschriebene Verhalten wiederherzustellen und noch mehr zu tun.
Weitere Infos zum Wiki-Artikel von RealGUD für ipdb.
Ursprüngliche Antwort:
Nachdem ich viele verschiedene Methoden zum Debuggen von Python ausprobiert habe, einschließlich aller in diesem Thread erwähnten Methoden, ist eine meiner bevorzugten Methoden zum Debuggen von Python mit IPython eingebettete Shells.
Definieren einer benutzerdefinierten eingebetteten IPython-Shell:
Fügen Sie Ihrem Skript Folgendes hinzu
PYTHONPATH
, damit die Methodeipsh()
verfügbar wird.Wenn ich dann etwas in meinem Code debuggen möchte, platziere ich es
ipsh()
genau an der Stelle, an der ich eine Objektinspektion usw. durchführen muss. Angenommen, ich möchtemy_function
unten debuggenEs benutzen:
und dann rufe ich auf
my_function(2)
eine der folgenden Arten auf:Unabhängig davon, wie ich es aufrufe, bleibt der Dolmetscher an der Zeile stehen, in der steht
ipsh()
. Sobald Sie fertig sind, können Sie dies tunCtrl-D
und Python setzt die Ausführung fort (mit allen von Ihnen vorgenommenen Variablenaktualisierungen). Beachten Sie, dass, wenn Sie den Code von einem regulären IPython aus ausführen, der IPython-Shell (Fall 2 oben), die neue IPython-Shell in derjenige verschachtelt ist, von der aus Sie sie aufgerufen haben. Dies ist vollkommen in Ordnung, aber es ist gut, sich dessen bewusst zu sein. Sobald der Interpreter an der Stelle von anhältipsh
, kann ich den Wert vona
(welche sein2
) überprüfen , sehen, welche Funktionen und Objekte definiert sind usw.Das Problem:
Die obige Lösung kann verwendet werden, um Python an einer beliebigen Stelle in Ihrem Code anzuhalten und Sie dann in einen vollwertigen IPython-Interpreter zu verschieben. Leider können Sie nach dem Aufrufen des Skripts keine Haltepunkte hinzufügen oder entfernen, was sehr frustrierend ist. Meiner Meinung nach ist dies das einzige, was IPython daran hindert, ein großartiges Debugging-Tool für Python zu werden.
Das Beste, was Sie jetzt tun können:
Eine Problemumgehung besteht darin,
ipsh()
a priori an den verschiedenen Stellen zu platzieren, an denen der Python-Interpreter eine IPython-Shell starten soll (z. B. abreakpoint
). Sie können dann zwischen verschiedenen vordefinierten, fest codierten "Haltepunkten" mit "springen"Ctrl-D
, wodurch die aktuell eingebettete IPython-Shell verlassen und erneut gestoppt wird, wenn der Interpreter den nächsten Aufruf von anruftipsh()
.Wenn Sie diesen Weg gehen, können Sie den "Debugging-Modus" beenden und alle nachfolgenden Haltepunkte
ipshell.dummy_mode = True
ignorieren,ipshell
indem Python alle nachfolgenden Instanziierungen des oben erstellten Objekts ignoriert .quelle
import inspect
bevor es funktionierte. Die Anpassung der Befehlszeile scheint für mich jedoch fehlerhaft zu sein.import ipdb; ipdb.set_trace()
? Vielleicht vermisse ich etwas, aber ich sehe nicht den Vorteil Ihrer viel komplizierteren Methode.Sie können die IPython-Sitzung von pudb aus starten und zur Debugging-Sitzung zurückkehren, wie Sie möchten .
Übrigens verwendet ipdb IPython hinter den Kulissen und Sie können tatsächlich IPython-Funktionen wie TAB-Vervollständigung und magische Befehle verwenden (der beginnt mit
%
). Wenn Sie mit ipdb einverstanden sind, können Sie es von IPython aus mit Befehlen wie%run
und starten%debug
. Die IPdB-Sitzung ist tatsächlich besser als die einfache IPython-Sitzung in dem Sinne, dass Sie im Stack-Trace usw. auf und ab gehen können. Was fehlt in der IPdb für die "Objektinspektion"?Außerdem bietet python.el, das mit Emacs> = 24.3 gebündelt ist, eine gute IPdb-Unterstützung.
quelle
M-x ansi-term
Puffer und binde dann den Isend-Modus , um meine Quellpuffer an den IPython-Puffer zu binden, damit ich Code mit einer Tastenkombination an den IPython-Interpreter senden kann, die die%paste
Magie automatisch an den IPython-Puffer sendet . Dadurch kann ich Regionen in IPython schnell testen. Ich führe meine Programme immer über diese IPython-Shell ausrun
und verwende sieembed()
zum Stoppen.ipdb
Debugging-Sitzung mit der entsprechenden Shell startenpython.el
und Dinge wiesend-region
etc. haben ? Wo finde ich im Allgemeinen weitere Informationen dazu?%run
oder%debug
. Ich denkeimport ipdb; ipdb.set_trace()
funktioniert auch. Ich glaube nicht, dass Sie mehrere Zeilen an ipdb senden können. Das ist die Einschränkung von ipdb. Aber wahrscheinlich%paste
funktioniert Trick. Möglicherweise möchten Sie eine Funktionsanforderung an IPython dev senden.Der Ansatz in der Antwort von @ gaborous scheint veraltet zu sein .
Der neue Ansatz scheint zu sein:
quelle
ipdb
Können Sie auf diese Weise beim Debuggen Anweisungen in der ipython-Shell verwenden?Ein "!" Das Symbol für Befehle, die Sie in pdb eingeben, scheint den gleichen Effekt zu haben wie etwas in einer IPython-Shell. Dies funktioniert für den Zugriff auf die Hilfe für eine bestimmte Funktion oder sogar für Variablennamen. Vielleicht hilft Ihnen das bis zu einem gewissen Grad. Beispielsweise,
Mit! Help (numpy.transpose) erhalten Sie jedoch die erwartete Hilfeseite zu numpy.transpose. Angenommen, Sie haben eine Variable l. Wenn Sie in pdb "l" eingeben, wird der Code aufgelistet, aber! L gibt den Wert von l aus.
quelle
Hast du diesen Tipp ausprobiert ?
quelle
Sie können
IPython
von innen beginnenipdb
!Induzieren Sie den
ipdb
Debugger 1 :Geben Sie IPython von innen in die
ipdb>
Konsole 2 ein :ipdb>
Kehren Sie von innen zur Konsole zurückIPython
:Wenn Sie das Glück haben, Emacs zu verwenden, können Sie die Dinge noch bequemer machen!
Dies erfordert die Verwendung
M-x shell
. Definieren Sie mityasnippet
und bm das folgende Snippet. Dadurch wird der Textipdb
im Editor durch dieset-trace
Zeile ersetzt. Nach dem Einfügen des Snippets wird die Linie hervorgehoben, damit sie leicht erkennbar und navigierbar ist. Verwenden SieM-x bm-next
zu navigieren.1 Alles in einer Zeile zum einfachen Löschen. Da
imports
dieses Formular nur einmal vorkommt, wird sichergestelltipdb
, dass es bei Bedarf ohne zusätzlichen Aufwand importiert wird.2 Sie können sich das Tippen ersparen, indem Sie
IPython
in Ihre.pdbrc
Datei importieren :Auf diese Weise können Sie einfach
embed()
von innen anrufenipdb
(natürlich nur, wenn IPython installiert ist).quelle
Eine Möglichkeit besteht darin, eine IDE wie Spyder zu verwenden, mit der Sie beim Debuggen mit Ihrem Code interagieren können (tatsächlich über eine IPython-Konsole). Tatsächlich ist Spyder sehr MATLAB-artig, was vermutlich beabsichtigt war. Dazu gehören Variableninspektoren, Variablenbearbeitung, integrierter Zugriff auf Dokumentation usw.
quelle
Die richtige, einfache, coole und genaue Antwort auf die Frage ist die Verwendung von% run macro mit dem Flag -d.
quelle
%save /tmp/foo.py x-y
den Code, den ich ausführen und debuggen möchte, und dann%run -d /tmp/foo.py
den Haltepunkt setzen, wo immer ich möchte. Gute Antwort!Wenn Sie exit () in die embedded () -Konsole eingeben, fahren Sie mit dem Code fort und fahren Sie mit der nächsten embedded () -Zeile fort.
quelle
Die Pyzo IDE verfügt über ähnliche Funktionen wie das OP. Sie müssen nicht im Debug-Modus starten. Ähnlich wie bei MATLAB werden die Befehle in der Shell ausgeführt. Wenn Sie einen Haltepunkt in einer Quellcodezeile einrichten, stoppt die IDE die Ausführung dort und Sie können auch reguläre IPython-Befehle debuggen und ausgeben.
Es scheint jedoch, dass das Einsteigen (noch?) Nicht gut funktioniert (dh in einer Zeile anhalten und dann in eine andere Funktion eintreten), es sei denn, Sie richten einen anderen Haltepunkt ein.
Aus MATLAB kommend, scheint dies die beste Lösung zu sein, die ich gefunden habe.
quelle
Ab Python 3.2 haben Sie den
interact
Befehl, mit dem Sie auf den gesamten Python / Ipython-Befehlsbereich zugreifen können.quelle
Das Ausführen von Emacs 'IPython-Shell und dem über pdb.set_trace () festgelegten Haltepunkt sollte funktionieren.
Überprüft mit python-mode.el, Mx ipython RET usw.
quelle
Neuen Code entwickeln
Debuggen in IPython
Zellbeispiel:
Vorhandenen Code debuggen
IPython beim Debuggen
pytest ... --pdbcls=IPython.terminal.debugger:TerminalPdb --pdb
breakpoint()
,python -m ipdb
usw.Gedanken zu Python
Ich stimme dem OP zu, dass viele Dinge, die MATLAB gut macht, Python immer noch nicht hat und wirklich sollte, da fast alles in der Sprache die Entwicklungsgeschwindigkeit gegenüber der Produktionsgeschwindigkeit bevorzugt. Vielleicht werde ich eines Tages mehr als nur triviale Fehlerbehebungen zu CPython beitragen.
https://github.com/ipython/ipython/commit/f042f3fea7560afcb518a1940daa46a72fbcfa68
Siehe auch Ist es möglich, Befehle in IPython mit Debugging auszuführen?
quelle