Schritt-für-Schritt-Debugging mit IPython

Von dem, was ich gelesen habe, gibt es zwei Möglichkeiten, um Code in Python zu debuggen:

Gibt es eine Möglichkeit, das Beste aus beiden Welten zu kombinieren? Dh

  1. In der Lage, Schritt-für-Schritt durch Ihren Code mit handlichen pdb / ipdb Tastenkombinationen.
  2. Bei einem solchen Schritt (zB bei einer gegebenen Anweisung) haben Sie Zugriff auf eine vollwertige IPython-Shell .

IPython-Debugging wie in MATLAB:

Ein Beispiel für diese Art von "erweitertem Debuggen" finden Sie in MATLAB, wo der Benutzer immer vollen Zugriff auf die MATLAB Engine / Shell hat und sie kann immer noch Schritt für Schritt durch ihren Code, definieren bedingte Breakpoints, etc. aus Was ich mit anderen Nutzern besprochen habe, das ist die Debugging-Funktion, die die Leute am meisten verpassen, wenn sie von MATLAB nach IPython wechseln.

IPython-Debugging in Emacs und anderen Editoren:

Ich möchte die Frage nicht zu genau machen, aber ich arbeite meistens in Emacs, also frage ich mich, ob es irgendeine Möglichkeit gibt, diese Funktionalität in sie zu bringen. Idealerweise würde Emacs (oder der Editor) dem Programmierer erlauben, Breakpoints irgendwo auf dem Code zu setzen und mit dem Interpreter oder Debugger zu kommunizieren, um ihn an der Stelle deiner Wahl zu stoppen und an einen vollständigen IPython-Interpreter an diesem Ort zu bringen.

11 Solutions collect form web for “Schritt-für-Schritt-Debugging mit IPython”

Was ist mit ipdb.set_trace ()? In deinem Code:

import ipdb; ipdb.set_trace()

Dies ermöglicht eine vollständige Überprüfung Ihres Codes, und Sie haben Zugriff auf Befehle wie c (weiter), n (führen Sie die nächste Zeile), s (Schritt in die Methode am Punkt) und so weiter.

Siehe ipdb repo und eine Liste der Befehle . IPython heißt jetzt Jupyter .


Ps: Beachten Sie, dass ein ipdb-Befehl Vorrang vor python-Code hat. Also, um zu schreiben list(foo) Sie benötigen print list(foo) .

(Update am 28. Mai 2016) Verwendung von RealGUD in Emacs

Für jedermann in Emacs, dieser Thread zeigt, wie alles zu erreichen, was im OP (und mehr) verwendet wird

  1. Ein neuer wichtiger Debugger in Emacs namens RealGUD, die mit jedem Debugger (einschließlich ipdb ) arbeiten können.
  2. Das Emacs-Paket isend-mode .

Die Kombination dieser beiden Pakete ist extrem leistungsstark und erlaubt es, genau das im OP beschriebene Verhalten neu zu erstellen und noch mehr zu machen.

Mehr Infos zum Wiki Artikel von RealGUD für ipdb.


Ursprüngliche Antwort:

Nachdem ich viele verschiedene Methoden zum Debuggen von Python, einschließlich alles, was in diesem Thread, eine meiner bevorzugten Möglichkeiten zum Debuggen von Python mit IPython ist mit eingebetteten Shells versucht.

Definieren einer benutzerdefinierten eingebetteten IPython-Shell:

Fügen Sie dem PYTHONPATH folgendes ein Skript PYTHONPATH , damit die Methode ipsh() verfügbar wird.

 import inspect # First import the embed function from IPython.terminal.embed import InteractiveShellEmbed from IPython.config.loader import Config # Configure the prompt so that I know I am in a nested (embedded) shell cfg = Config() prompt_config = cfg.PromptManager prompt_config.in_template = 'N.In <\\#>: ' prompt_config.in2_template = ' .\\D.: ' prompt_config.out_template = 'N.Out<\\#>: ' # Messages displayed when I drop into and exit the shell. banner_msg = ("\n**Nested Interpreter:\n" "Hit Ctrl-D to exit interpreter and continue program.\n" "Note that if you use %kill_embedded, you can fully deactivate\n" "This embedded instance so it will never turn on again") exit_msg = '**Leaving Nested interpreter' # Wrap it in a function that gives me more context: def ipsh(): ipshell = InteractiveShellEmbed(config=cfg, banner1=banner_msg, exit_msg=exit_msg) frame = inspect.currentframe().f_back msg = 'Stopped at {0.f_code.co_filename} at line {0.f_lineno}'.format(frame) # Go back one level! # This is needed because the call to ipshell is inside the function ipsh() ipshell(msg,stack_depth=2) 

Dann, wann immer ich etwas in meinem Code debuggen möchte, platziere ich ipsh() direkt an den Ort, an dem ich Objektinspektion machen muss. Zum Beispiel sagen wir, dass ich my_function unten debuggen my_function

Es benutzen:

 def my_function(b): a = b ipsh() # <- This will embed a full-fledged IPython interpreter a = 4 

Und dann my_function(2) ich my_function(2) auf eine der folgenden Weisen auf:

  1. Entweder durch Ausführen eines Python-Programms, das diese Funktion aus einer Unix-Shell aufruft
  2. Oder direkt von IPython anrufen

Unabhängig davon, wie ich es ipsh() , stoppt der Dolmetscher an der Linie, die ipsh() sagt. Sobald Sie fertig sind, können Sie Ctrl-D und Python wird die Ausführung fortsetzen (mit allen Variablen Updates, die Sie gemacht haben). Beachten Sie, dass, wenn Sie den Code aus einer regulären IPython die IPython-Shell (Fall 2 oben) ausführen, wird die neue IPython-Shell in die verschachtelte, von der Sie es aufgerufen haben, was ganz gut ist, aber es ist gut, sich bewusst zu sein. Entweder, sobald der Dolmetscher an der Stelle von ipsh , kann ich den Wert a (was 2 ) überprüfen, welche Funktionen und Objekte definiert sind usw.

Das Problem:

Die obige Lösung kann verwendet werden, um Python-Stopp überall zu haben, wo du in deinem Code willst und dann dich in einen vollwertigen IPython-Interpreter bringen kannst. Leider lässt es nicht zulassen, dass Sie Breakpoints hinzufügen oder entfernen, sobald Sie das Skript aufrufen, was sehr frustrierend ist. Meiner Meinung nach ist dies das einzige, was verhindert, dass IPython ein großes Debugging-Tool für Python wird.

Das Beste, was du jetzt tun kannst:

Ein Workaround ist, ipsh() a priori an den verschiedenen Orten zu platzieren, wo der Python-Interpreter eine IPython-Shell (dh einen breakpoint ) starten soll. Sie können dann zwischen verschiedenen vordefinierten, hartcodierten "Breakpoints" mit Ctrl-D "springen", die die aktuelle eingebettete IPython-Shell beenden und wieder stoppen werden, wenn der Interpreter den nächsten Aufruf von ipsh() trifft.

Wenn du diesen Weg gehst, dann gehst du einen Weg, um "Debugging-Modus" zu ipshell.dummy_mode = True und alle nachfolgenden Breakpoints zu ignorieren, ist es, ipshell.dummy_mode = True was Python dazu veranlasst, irgendwelche nachfolgenden Instanzen des ipshell Objekts zu ignorieren, die wir oben erstellt haben.

Sie können die IPython-Sitzung von pudb starten und zurück zur Debugging-Sitzung gehen, wie Sie möchten .

BTW, ipdb benutzt IPython hinter den Kulissen und man kann eigentlich die IPython-Funktionalität wie TAB-Abschluss und magische Befehle verwenden (die man beginnt mit % ). Wenn Sie mit ipdb OK sind, können Sie es von IPython mit Befehlen wie %run und %debug starten. Ipdb session ist eigentlich besser als normales IPython eins in dem Sinne, dass man in der Stack-Trace auf und ab gehen kann. Was fehlt in ipdb für "Objektinspektion"?

Auch python.el gebündelt mit Emacs> = 24.3 hat nette ipdb Unterstützung.

Präfixieren eines "!" Symbol für Befehle, die Sie in pdb eingeben, scheint die gleiche Wirkung zu haben wie etwas in einer IPython-Shell zu tun. Dies funktioniert für den Zugriff auf Hilfe für eine bestimmte Funktion oder sogar Variablennamen. Vielleicht hilft dir das bis zu einem gewissen Grad. Beispielsweise,

 ipdb> help(numpy.transpose) *** No help on (numpy.transpose) 

Aber Hilfe (numpy.transpose) gibt dir die erwartete Hilfeseite auf numpy.transpose. Ähnlich für Variablennamen, sagen Sie, Sie haben eine Variable l, Eingabe von "l" in pdb listet den Code, aber! L druckt den Wert von l.

Hast du diesen Tipp probiert ?

Oder besser noch, nimm ipython und ruf:

 from IPython.Debugger import Tracer; debug_here = Tracer() 

Dann kannst du einfach benutzen

 debug_here() 

Wann immer du einen Haltepunkt setzen willst

Sieht aus wie der Ansatz in @ Gaborous Antwort ist veraltet .

Der neue Ansatz scheint zu sein:

 from IPython.core import debugger debug = debugger.Pdb().set_trace def buggy_method(): debug() 

Eine Option ist, eine IDE wie Spyder zu verwenden, die es Ihnen erlauben sollte, mit Ihrem Code während des Debuggens zu interagieren (mit einer IPython-Konsole in der Tat). In der Tat, Spyder ist sehr MATLAB-like, die ich vermute, war vorsätzlich. Dazu gehören variable Inspektoren, variable Bearbeitung, integrierter Zugriff auf Dokumentation, etc.

Wenn du exit () in der embed () – Konsole eingibst, geht der Code weiter und gehe zur nächsten embed () – Zeile.

Die Pyzo IDE hat ähnliche Fähigkeiten wie das OP gefragt hat. Sie müssen nicht im Debug-Modus starten. Ähnlich wie bei MATLAB werden die Befehle in der Shell ausgeführt. Wenn du einen Break-Point in einer Quellcodezeile einrufst, stoppt die IDE die Ausführung dort und du kannst auch regelmäßige IPython-Befehle debuggen und ausgeben.

Es scheint aber, dass Schritt-in nicht (noch?) Gut funktioniert (dh in einer Zeile zu stoppen und dann in eine andere Funktion), wenn Sie einen anderen Bruchpunkt einrichten.

Dennoch kommt es von MATLAB, das ist die beste Lösung, die ich gefunden habe

%pdb niemand erwähnte %pdb flag. Rufen %pdb einfach %pdb in IPython an und wenn ein Fehler auftritt, werden Sie automatisch auf ipdb . Während du das ipdb nicht sofort hast, bist ipdb nachher in ipdb .

Dies macht das Debuggen einzelner Funktionen einfach, da man nur eine Datei mit %load und dann eine Funktion ausführen kann. Sie könnten einen Fehler mit einer assert an der richtigen Stelle erzwingen.

Von innen aus gehen Emacs 'IPython-Shell und Breakpoint gesetzt über pdb.set_trace () sollte funktionieren.

Geprüft mit python-mode.el, Mx ipython RET etc.

  • Python Debugger (pdb) gestoppt Handing up / down Pfeile, zeigt ^ [[A statt
  • Wie sehen Sie eine Variable in pdb
  • Debugging von Python-Programmen in emacs
  • Wie man sublimierte Plugins während der Entwicklung debuggt
  • Wie stelle ich sys.excepthook ein, um pdb global in python aufzurufen?
  • Verfolgung der Ausführung einer Python-Programmzeile / Anweisung per Zeile programmgesteuert
  • Zwei verschiedene Werte für dieselbe Variable "args"
  • Ist es möglich, in ipython von Code zu gehen?
  • Python (pdb) - Ausschalten der Befehle zum Ausführen
  • Bdbquit aufgewachsen beim Debuggen von Python
  • Wie ändere ich einen Wert beim Debuggen von python mit pdb?
  • Python ist die beste Programmiersprache der Welt.