Python-Debugging-Tipps [geschlossen]


164

Was sind Ihre besten Tipps zum Debuggen von Python?

Bitte listen Sie nicht nur einen bestimmten Debugger auf, ohne zu sagen, was er tatsächlich kann.

verbunden


Antworten:


139

PDB

Sie können das pdb-Modul verwenden, an einer pdb.set_trace()beliebigen Stelle einfügen und es fungiert als Haltepunkt.

>>> import pdb
>>> a="a string"
>>> pdb.set_trace()
--Return--
> <stdin>(1)<module>()->None
(Pdb) p a
'a string'
(Pdb)

Um die Ausführung fortzusetzen, verwenden Sie c(oder contoder continue).

Es ist möglich, beliebige Python-Ausdrücke mit pdb auszuführen. Wenn Sie beispielsweise einen Fehler finden, können Sie den Code korrigieren und dann einen Typausdruck eingeben, um den gleichen Effekt im laufenden Code zu erzielen

ipdb ist eine Version von pdb für IPython . Es ermöglicht die Verwendung von pdb mit allen IPython-Funktionen einschließlich der Tab-Vervollständigung.

Es ist auch möglich, pdb so einzustellen, dass es automatisch mit einer nicht erfassten Ausnahme ausgeführt wird.

Pydb wurde als erweiterte Version von Pdb geschrieben. Leistungen?


Hier ist ein Artikel über die Verwendung von pdb: sontek.net/debugging-python-with-pdb
sontek

Persönlich mag ich ipdb besser.
Sardathrion - gegen SE Missbrauch

1
Anscheinend gibt es eine Neufassung von pydb namens pydbgr
Ehtesh Choudhury

SublimeText hat ein großartiges Plugin zum Hinzufügen von Python-Haltepunkten zum Code: sublime.wbond.net/packages/Python%20Breakpoints
Dennis Golomazov

Wenn Sie eine Webanwendung entwickeln, fügen Sie myserver.com/pdbim Debug-Modus eine Ansicht hinzu , die dies einfach tut import pdb; pdb.set_trace(). Wenn Sie Flask / Werkzeug mit einem interaktiven Debugger verwenden, können Sie auch eine Ansicht haben, die dies nur tut assert False.
osa

78

http://pypi.python.org/pypi/pudb , ein konsolenbasierter Python-Debugger im Vollbildmodus.

Ziel ist es, alle Vorteile moderner GUI-basierter Debugger in einem leichteren und tastaturfreundlicheren Paket bereitzustellen. Mit PuDB können Sie Code genau dort debuggen, wo Sie ihn schreiben und testen - in einem Terminal. Wenn Sie mit den hervorragenden (aber heutzutage alten) DOS-basierten Turbo Pascal- oder C-Tools gearbeitet haben, kommt Ihnen die Benutzeroberfläche von PuDB möglicherweise bekannt vor.

Pudb Screenshot

Gut zum Debuggen von eigenständigen Skripten, einfach ausführen

python -m pudb.run my-script.py

Installieren Sie mitpip install pudb
congusbongus

40

Wenn Sie pdb verwenden, können Sie Aliase für Verknüpfungen definieren. Ich benutze diese:

# Ned's .pdbrc

# Print a dictionary, sorted. %1 is the dict, %2 is the prefix for the names.
alias p_ for k in sorted(%1.keys()): print "%s%-15s= %-80.80s" % ("%2",k,repr(%1[k]))

# Print the instance variables of a thing.
alias pi p_ %1.__dict__ %1.

# Print the instance variables of self.
alias ps pi self

# Print the locals.
alias pl p_ locals() local:

# Next and list, and step and list.
alias nl n;;l
alias sl s;;l

# Short cuts for walking up and down the stack
alias uu u;;u
alias uuu u;;u;;u
alias uuuu u;;u;;u;;u
alias uuuuu u;;u;;u;;u;;u
alias dd d;;d
alias ddd d;;d;;d
alias dddd d;;d;;d;;d
alias ddddd d;;d;;d;;d;;d

Wie definieren Sie diesen Alias?
Casebash

9
Setzen Sie dieses Zeug in ~ / .pdbrc
Ned Batchelder

Unter Windows können Sie es in ~ / _ipython / ipythonrc.ini
Fastmultiplication

33

Protokollierung

Python verfügt bereits über ein hervorragendes integriertes Protokollierungsmodul . Möglicherweise möchten Sie hier die Protokollierungsvorlage verwenden .

Mit dem Protokollierungsmodul können Sie einen Wichtigkeitsgrad angeben. Während des Debuggens können Sie alles protokollieren, während Sie während des normalen Betriebs möglicherweise nur kritische Dinge protokollieren. Sie können Dinge ein- und ausschalten.

Die meisten Benutzer verwenden nur einfache Druckanweisungen zum Debuggen und entfernen dann die Druckanweisungen. Es ist besser, sie zu belassen, aber zu deaktivieren. Wenn Sie dann einen anderen Fehler haben, können Sie einfach alles wieder aktivieren und Ihre Protokolle überprüfen.

Dies kann der beste Weg sein, um Programme zu debuggen, die schnell erledigt werden müssen, z. B. Netzwerkprogramme, die reagieren müssen, bevor das andere Ende der Netzwerkverbindung abläuft und nicht mehr funktioniert. Möglicherweise haben Sie nicht viel Zeit, um einen Debugger in einem Schritt auszuführen. Aber Sie können einfach Ihren Code laufen lassen und alles protokollieren, dann die Protokolle durchforsten und herausfinden, was wirklich passiert.

BEARBEITEN: Die ursprüngliche URL für die Vorlagen lautete: http://aymanh.com/python-debugging-techniques

Diese Seite fehlt, daher habe ich sie durch einen Verweis auf den unter archive.org gespeicherten Schnappschuss ersetzt: http://web.archive.org/web/20120819135307/http://aymanh.com/python-debugging-techniques

Falls es wieder verschwindet, hier sind die Vorlagen, die ich erwähnt habe. Dies ist Code aus dem Blog; Ich habe es nicht geschrieben.

import logging
import optparse

LOGGING_LEVELS = {'critical': logging.CRITICAL,
                  'error': logging.ERROR,
                  'warning': logging.WARNING,
                  'info': logging.INFO,
                  'debug': logging.DEBUG}

def main():
  parser = optparse.OptionParser()
  parser.add_option('-l', '--logging-level', help='Logging level')
  parser.add_option('-f', '--logging-file', help='Logging file name')
  (options, args) = parser.parse_args()
  logging_level = LOGGING_LEVELS.get(options.logging_level, logging.NOTSET)
  logging.basicConfig(level=logging_level, filename=options.logging_file,
                      format='%(asctime)s %(levelname)s: %(message)s',
                      datefmt='%Y-%m-%d %H:%M:%S')

  # Your program goes here.
  # You can access command-line arguments using the args variable.

if __name__ == '__main__':
  main()

Und hier ist seine Erklärung, wie man das Obige benutzt. Auch hier bekomme ich keine Anerkennung:


Standardmäßig druckt das Protokollierungsmodul kritische Meldungen, Fehlermeldungen und Warnmeldungen. Verwenden Sie Folgendes, um dies so zu ändern, dass alle Ebenen gedruckt werden:

$ ./your-program.py --logging=debug

Verwenden Sie Folgendes, um Protokollnachrichten an eine Datei mit dem Namen debug.log zu senden:

$ ./your-program.py --logging-level=debug --logging-file=debug.log


1
Das Problem mit dem Protokollierungsmodul besteht darin, dass es stark mit Unicode bricht und verschiedene Problemumgehungen erforderlich sind, damit es in einer internationalisierten Anwendung funktioniert. Dies ist jedoch immer noch die beste Protokollierungslösung für Python.
Jacek Konieczny

Der Link "Protokollierungsvorlage hier" ist tot. Bitte aktualisieren.
Yohann

20

Es ist möglich zu drucken, welche Python-Zeilen ausgeführt werden (danke Geo!). Dies hat eine beliebige Anzahl von Anwendungen. Sie können es beispielsweise ändern, um zu überprüfen, wann bestimmte Funktionen aufgerufen werden, oder etwas wie ## hinzufügen, damit nur bestimmte Zeilen verfolgt werden.

code.interact führt Sie in eine interaktive Konsole

import code; code.interact(local=locals())

Wenn Sie einfach auf Ihren Konsolenverlauf zugreifen möchten, lesen Sie: " Kann ich einen Verlaufsmechanismus wie in der Shell haben? " (Muss danach suchen).

Die automatische Vervollständigung kann für den Interpreter aktiviert werden .


19

ipdb ist wie pdb, mit der Großartigkeit von ipython.


5
Könnten Sie weitere Details hinzufügen, was es tun kann?
Casebash

17

print Aussagen

  • Einige Leute empfehlen eine debug_printFunktion anstelle von Drucken, um das Deaktivieren zu vereinfachen
  • Das pprintModul ist für komplexe Strukturen von unschätzbarem Wert

3
+1 wenn jeder Debugger fehlschlägt, ist print dein Freund, ja debug_print wäre eine nette Ergänzung
Anurag Uniyal

Ich
drucke im

4
Eigentlich macht das Log-Modul genau das.
E-Satis

Stimmt, aber die Protokollierung muss eingerichtet werden. Ich werde lernen, wie man das Modul nach Ehrungen benutzt
Casebash

Drucken kann in einfachen Fällen hilfreich sein, insbesondere bei der Entwicklung von Projekten mit geringer Startzeit. Auf der anderen Seite kann es süchtig machen und die Verwendung über pdb oder einen anderen Debugger in komplexeren Szenarien verursacht normalerweise Kopfschmerzen
vinilios

16

der offensichtliche Weg, um ein Skript zu debuggen

python -m pdb script.py
  • nützlich, wenn dieses Skript eine Ausnahme auslöst
  • Nützlich, wenn der Befehl virtualenv und pdb nicht mit der Python-Version von venvs ausgeführt wird.

wenn Sie nicht genau wissen, wo sich das Skript befindet

python -m pdb ``which <python-script-name>``

15

PyDev

PyDev hat einen ziemlich guten interaktiven Debugger. Es verfügt über Watch-Ausdrücke, Hover-to-Evaluate-, Thread- und Stack-Listen und (fast) alle üblichen Annehmlichkeiten, die Sie von einem modernen visuellen Debugger erwarten. Sie können sogar eine Verbindung zu einem laufenden Prozess herstellen und Remote-Debugging durchführen.

Wie andere visuelle Debugger finde ich es jedoch hauptsächlich für einfache Probleme oder für sehr komplizierte Probleme nützlich, nachdem ich alles andere ausprobiert habe. Ich mache immer noch den größten Teil des schweren Hebens mit Holzeinschlag.


Hat es die Fähigkeit zu bearbeiten und fortzufahren?
Casebash

@CaseBash nein, aber diese Funktion ist geplant. Auch ohne sie ist die Geschwindigkeit und Leichtigkeit des Einstellens / Aufhebens von Haltepunkten und des
Durchsuchens


12

Winpdb ist sehr schön und im Gegensatz zu seinem Namen völlig plattformübergreifend.

Es hat einen sehr schönen prompt-basierten und GUI-Debugger und unterstützt Remote-Debugging.


@Casebash - weitere Details hinzugefügt
Orip

1
+1 Dies ist der einzige Python-Debugger, den ich bisher gefunden habe und der Multithreading unterstützt.
Lee Netherton

Seien Sie vorsichtig beim "Umgang" mit Multithreading - jede Ausnahme in einem Thread führt dazu, dass der gesamte Prozess einfriert. Keine schlechte Sache, wenn Sie sich dessen bewusst sind, sehr schmerzhaft, wenn Sie nicht sind
Walt W

Das Projekt sieht ab April 2014 tot aus
Alojz Janez

7

In Vim habe ich diese drei Bindungen:

map <F9> Oimport rpdb2; rpdb2.start_embedded_debugger("asdf") #BREAK<esc>
map <F8> Ofrom nose.tools import set_trace; set_trace() #BREAK<esc>
map <F7> Oimport traceback, sys; traceback.print_exception(*sys.exc_info()) #TRACEBACK<esc>

rpdb2ist ein Remote Python Debugger, der mit WinPDB, einem soliden grafischen Debugger, verwendet werden kann. Weil ich weiß, dass Sie fragen werden, kann es alles, was ich von einem grafischen Debugger erwarte :)

Ich benutze pdbvon, nose.toolsdamit ich Unit-Tests sowie normalen Code debuggen kann.

Schließlich wird bei der F7Zuordnung ein Traceback gedruckt (ähnlich der Art, die Sie erhalten, wenn eine Ausnahme an die Spitze des Stapels sprudelt). Ich fand es mehr als ein paar Mal wirklich nützlich.


4

Definieren Sie nützliche repr () -Methoden für Ihre Klassen (damit Sie sehen können, was ein Objekt ist) und verwenden Sie das Format repr () oder "% r"% (...) oder "... {0! R} .." (...) in Ihren Debug-Nachrichten / Protokollen ist meiner Meinung nach ein Schlüssel zum effizienten Debuggen.

Außerdem verwenden die in anderen Antworten erwähnten Debugger die repr () -Methoden.


2

Abrufen eines Stack-Trace von einer laufenden Python-Anwendung

Es gibt einige Tricks hier . Diese beinhalten

  • Einbruch in einen Interpreter / Drucken einer Stapelverfolgung durch Senden eines Signals
  • Abrufen eines Stack-Trace aus einem unvorbereiteten Python-Prozess
  • Ausführen des Interpreters mit Flags, um ihn für das Debuggen nützlich zu machen

2

Wenn Sie keine Zeit in Debuggern verbringen möchten (und die schlechte Benutzerfreundlichkeit der pdbBefehlszeilenschnittstelle nicht schätzen ), können Sie die Ausführungsablaufverfolgung sichern und später analysieren. Beispielsweise:

python -m trace -t setup.py install > execution.log

Dadurch wird die gesamte Quellausführungszeile an setup.py installausgegeben execution.log.

Um das Anpassen der Trace-Ausgabe und das Schreiben eigener Tracer zu vereinfachen , habe ich einige Codeteile im xtrace- Modul (gemeinfrei) zusammengestellt.


1

Wenn möglich, debugge ich M-x pdbin Emacs für das Debuggen auf Quellenebene.


1

Es gibt einen vollständigen Online-Kurs namens " Software Debugging " von Andreas Zeller über Udacity mit Tipps zum Debuggen:

Kursübersicht

In dieser Klasse lernen Sie, wie Sie Programme systematisch debuggen, den Debugging-Prozess automatisieren und mehrere automatisierte Debugging-Tools in Python erstellen.

Warum diesen Kurs belegen?

Am Ende dieses Kurses haben Sie ein solides Verständnis für systematisches Debuggen, wissen, wie man das Debuggen automatisiert, und haben mehrere funktionale Debugging-Tools in Python erstellt.

Voraussetzungen und Anforderungen

Grundkenntnisse in Programmierung und Python auf der Ebene von Udacity CS101 oder besser sind erforderlich. Grundlegendes Verständnis der objektorientierten Programmierung ist hilfreich.

Sehr empfehlenswert.


0

Wenn Sie eine schöne grafische Möglichkeit zum lesbaren Drucken Ihres Anrufstapels wünschen, lesen Sie dieses Dienstprogramm: https://github.com/joerick/pyinstrument

Über die Befehlszeile ausführen:

python -m pyinstrument myscript.py [args...]

Als Modul ausführen:

from pyinstrument import Profiler

profiler = Profiler()
profiler.start()

# code you want to profile

profiler.stop()
print(profiler.output_text(unicode=True, color=True))

Laufen Sie mit Django:

Fügen Sie einfach pyinstrument.middleware.ProfilerMiddlewarezu MIDDLEWARE_CLASSES, fügen Sie dann ?profilebis zum Ende der Anforderungs - URL der Profiler zu aktivieren.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.