Ich habe diese Python-Anwendung, die von Zeit zu Zeit hängen bleibt und ich kann nicht herausfinden, wo.
Gibt es eine Möglichkeit, dem Python-Interpreter zu signalisieren, dass er Ihnen den genauen Code anzeigt, der ausgeführt wird?
Eine Art On-the-Fly-Stacktrace?
Verwandte Fragen:
Antworten:
Ich habe ein Modul, das ich für Situationen wie diese verwende - in denen ein Prozess lange läuft, aber manchmal aus unbekannten und nicht reproduzierbaren Gründen stecken bleibt. Es ist ein bisschen hackig und funktioniert nur unter Unix (erfordert Signale):
Rufen Sie zur Verwendung einfach die Funktion listen () auf, wenn Ihr Programm gestartet wird (Sie können es sogar in site.py einfügen, damit alle Python-Programme es verwenden), und lassen Sie es laufen. Senden Sie dem Prozess jederzeit ein SIGUSR1-Signal mit kill oder in Python:
Dies führt dazu, dass das Programm an der Stelle, an der es sich gerade befindet, zu einer Python-Konsole wechselt, die Stapelverfolgung anzeigt und Sie die Variablen bearbeiten können. Verwenden Sie control-d (EOF), um die Ausführung fortzusetzen (beachten Sie jedoch, dass Sie wahrscheinlich alle E / A usw. an dem von Ihnen signalisierten Punkt unterbrechen werden, damit es nicht vollständig aufdringlich ist.
Ich habe ein anderes Skript, das dasselbe tut, außer dass es über eine Pipe mit dem laufenden Prozess kommuniziert (um das Debuggen von Hintergrundprozessen usw. zu ermöglichen). Es ist ein bisschen groß, hier zu posten, aber ich habe es als Python-Kochbuchrezept hinzugefügt .
quelle
faulthandler
Modul (und seinen Backport auf PyPI) für einen C-Level-Signalhandler, der den Python-Stack druckt, ohne dass die Interpreter-Schleife reagieren muss.Der Vorschlag, einen Signalhandler zu installieren, ist gut und ich verwende ihn häufig. Beispielsweise installiert bzr standardmäßig einen SIGQUIT-Handler , der aufgerufen wird
pdb.set_trace()
, um Sie sofort in eine pdb- Eingabeaufforderung einzufügen . ( Die genauen Details finden Sie in der Quelle des Moduls bzrlib.breakin .) Mit pdb können Sie nicht nur den aktuellen Stack-Trace abrufen, sondern auch Variablen usw. überprüfen.Manchmal muss ich jedoch einen Prozess debuggen, in dem ich nicht die Voraussicht hatte, den Signalhandler zu installieren. Unter Linux können Sie gdb an den Prozess anhängen und einen Python-Stack-Trace mit einigen gdb-Makros abrufen. Geben Sie http://svn.python.org/projects/python/trunk/Misc/gdbinit ein
~/.gdbinit
und dann:gdb -p
PID
pystack
Es ist leider nicht ganz zuverlässig, aber es funktioniert die meiste Zeit.
Schließlich kann das Anhängen
strace
oft eine gute Vorstellung davon geben, was ein Prozess tut.quelle
python-dbg
). Ohne diese Symbole scheinen Sie nicht viele nützliche Informationen zu erhalten.Unable to locate python frame
zu jedem BefehlIch habe es fast immer mit mehreren Threads zu tun, und der Haupt-Thread macht im Allgemeinen nicht viel. Am interessantesten ist es also, alle Stapel zu sichern (was eher dem Java-Speicherauszug ähnelt). Hier ist eine Implementierung, die auf diesem Blog basiert :
quelle
Mit Pyrasite können Sie einen Stack-Trace eines unvorbereiteten Python-Programms abrufen , das in einem Standard- Python ohne Debugging-Symbole ausgeführt wird . Hat bei Ubuntu Trusty wie ein Zauber für mich funktioniert:
(Hutspitze an @Albert, dessen Antwort unter anderem einen Zeiger darauf enthielt.)
quelle
dump_stacks.py
import traceback; traceback.print_stack()
traceback -l
gibt Ihnen eine Liste vordefinierter Python-Skripte, die Sie verwenden können, unddump_stacks.py
ist eines davon. Wenn Sie Ihre eigene verwenden (z. B. um eine Stapelverfolgung in eine Datei zu schreiben), ist es möglicherweise ratsam, einen anderen Namen zu verwenden.apt-get install gdb python-dbg
(oder ein gleichwertiges Produkt) aus, bevor Sie Pyrasit ausführen, da es sonst lautlos ausfällt. Funktioniert sonst wie ein Zauber!Sie können den Stack-Trace auch gut formatieren (siehe Dokumente) .
Bearbeiten : Um das von @Douglas Leeder vorgeschlagene Verhalten von Java zu simulieren, fügen Sie Folgendes hinzu:
zum Startcode in Ihrer Anwendung. Anschließend können Sie den Stapel drucken, indem Sie ihn
SIGUSR1
an den laufenden Python-Prozess senden .quelle
Das Traceback- Modul hat einige nette Funktionen, darunter: print_stack:
quelle
import traceback; f = open('/tmp/stack-trace.log', 'w') traceback.print_stack(file=f) f.close()
Sie können das Faulthandler-Modul ausprobieren . Installieren Sie es mit
pip install faulthandler
und fügen Sie hinzu:zu Beginn Ihres Programms. Senden Sie dann SIGUSR1 an Ihren Prozess (z
kill -USR1 42
. B. :), um den Python-Traceback aller Threads für die Standardausgabe anzuzeigen. In der Dokumentation finden Sie weitere Optionen (z. B. Anmelden in einer Datei) und andere Möglichkeiten zum Anzeigen des Tracebacks.Das Modul ist jetzt Teil von Python 3.3. Informationen zu Python 2 finden Sie unter http://faulthandler.readthedocs.org/.
quelle
Was mir hier wirklich geholfen hat, ist der Tipp von spiv (den ich abstimmen und kommentieren würde, wenn ich die Reputationspunkte hätte), um einen Stack-Trace aus einem unvorbereiteten Python-Prozess herauszuholen . Nur dass es nicht funktioniert hat, bis ich das gdbinit-Skript geändert habe . Damit:
Laden Sie http://svn.python.org/projects/python/trunk/Misc/gdbinit herunter und fügen Sie es ein
~/.gdbinit
Bearbeiten Sie es und wechseln Sie[bearbeiten: nicht mehr benötigt; Die verknüpfte Datei hat diese Änderung bereits ab dem 14.01.2010]PyEval_EvalFrame
zuPyEval_EvalFrameEx
Gdb anhängen:
gdb -p PID
Holen Sie sich den Python-Stack-Trace:
pystack
quelle
No symbol "co" in current context.
Ich würde dies als Kommentar zu Haridsvs Antwort hinzufügen , aber mir fehlt der Ruf, dies zu tun:
Einige von uns stecken immer noch in einer Version von Python fest, die älter als 2.6 ist (erforderlich für Thread.ident), daher habe ich den Code in Python 2.5 zum Laufen gebracht (allerdings ohne dass der Thread-Name angezeigt wird):
quelle
python -dv yourscript.py
Dadurch wird der Interpreter im Debug-Modus ausgeführt und Sie erhalten einen Überblick darüber, was der Interpreter tut.
Wenn Sie den Code interaktiv debuggen möchten, sollten Sie ihn folgendermaßen ausführen:
python -m pdb yourscript.py
Das weist den Python-Interpreter an, Ihr Skript mit dem Modul "pdb" auszuführen, das der Python-Debugger ist. Wenn Sie es so ausführen, wird der Interpreter im interaktiven Modus ausgeführt, ähnlich wie GDB
quelle
Schauen Sie sich das
faulthandler
Modul an, das neu in Python 3.3 ist. Einfaulthandler
Backport zur Verwendung in Python 2 ist auf PyPI verfügbar.quelle
Unter Solaris können Sie pstack (1) verwenden. Es sind keine Änderungen am Python-Code erforderlich. z.B.
quelle
pstack
, das dasselbe tutWenn Sie auf einem Linux-System arbeiten, nutzen Sie die Attraktivität von
gdb
Python-Debug-Erweiterungen (kann inpython-dbg
oder impython-debuginfo
Paket enthalten sein). Es hilft auch bei Multithread-Anwendungen, GUI-Anwendungen und C-Modulen.Führen Sie Ihr Programm aus mit:
Dies weist
gdb
an, es vorzubereitenpython <programname>.py <arguments>
und zur
entfernen.Wenn Sie das Programm hängen lassen, wechseln Sie in die
gdb
Konsole, drücken Sie Ctr+Cund führen Sie Folgendes aus:Siehe Beispielsitzung und weitere Informationen hier und hier .
quelle
Ich habe eine Weile nach einer Lösung gesucht, um meine Threads zu debuggen, und ich habe sie hier dank haridsv gefunden. Ich verwende eine leicht vereinfachte Version mit traceback.print_stack ():
Für meine Bedürfnisse filtere ich Threads auch nach Namen.
quelle
Es lohnt sich, sich Pydb anzusehen , "eine erweiterte Version des Python-Debuggers, die lose auf dem Befehlssatz gdb basiert". Es enthält Signalmanager, die sich um das Starten des Debuggers kümmern können, wenn ein bestimmtes Signal gesendet wird.
Ein Summer of Code-Projekt aus dem Jahr 2006 befasste sich mit dem Hinzufügen von Remote-Debugging-Funktionen zu pydb in einem Modul namens mpdb .
quelle
Ich habe ein Tool gehackt, das sich in einen laufenden Python-Prozess einfügt und Code einfügt, um eine Python-Shell zu erhalten.
Siehe hier: https://github.com/albertz/pydbattach
quelle
pyrasite
hat perfekt funktioniert!Es kann mit ausgezeichnetem Py-Spy gemacht werden . Es ist ein Sampling-Profiler für Python-Programme , daher besteht seine Aufgabe darin, sich an Python-Prozesse anzuhängen und deren Aufrufstapel zu testen. Daher
py-spy dump --pid $SOME_PID
ist alles, was Sie tun müssen, um Aufrufstapel aller Threads im$SOME_PID
Prozess zu sichern . In der Regel sind erweiterte Berechtigungen erforderlich (um den Speicher des Zielprozesses zu lesen).Hier ist ein Beispiel dafür, wie es für eine Python-Anwendung mit Thread aussieht.
quelle
pyringe ist ein Debugger, der ohne vorherige Einrichtung mit laufenden Python-Prozessen, Druckstapel-Traces, Variablen usw. interagieren kann.
Obwohl ich in der Vergangenheit häufig die Signalhandler-Lösung verwendet habe, kann es in bestimmten Umgebungen immer noch schwierig sein, das Problem zu reproduzieren.
quelle
pyrasite
arbeitete für mich wie ein Zauber.Es gibt keine Möglichkeit, sich in einen laufenden Python-Prozess einzubinden und vernünftige Ergebnisse zu erzielen. Was ich mache, wenn Prozesse blockieren, ist, mich einzumischen und herauszufinden, was genau passiert.
Leider ist oft strace der Beobachter, der die Rennbedingungen "repariert", so dass die Ausgabe auch dort unbrauchbar wird.
quelle
Sie können dazu PuDB verwenden , einen Python-Debugger mit einer Curses-Schnittstelle. Einfach hinzufügen
zu Ihrem Code und verwenden Sie Strg-C, wenn Sie brechen möchten. Sie können
c
mehrmals fortfahren und erneut brechen, wenn Sie es verpassen und es erneut versuchen möchten.quelle
Ich bin im GDB-Camp mit den Python-Erweiterungen. Folgen Sie https://wiki.python.org/moin/DebuggingWithGdb , was bedeutet
dnf install gdb python-debuginfo
odersudo apt-get install gdb python2.7-dbg
gdb python <pid of running process>
py-bt
Beachten Sie auch
info threads
undthread apply all py-bt
.quelle
Traceback (most recent call first): Python Exception <class 'gdb.error'> No frame is currently selected.: Error occurred in Python command: No frame is currently selected.
beim Laufenpy-bt
ingdb
?sudo
. Ich musste auchgdb pyton <pid>
als Sudo laufen .So debuggen Sie eine Funktion in der Konsole :
Erstellen Sie eine Funktion, in der Sie pdb.set_trace () verwenden , und dann die Funktion, die Sie debuggen möchten.
Rufen Sie dann die erstellte Funktion auf:
Viel Spaß beim Debuggen :)
quelle
Ich kenne nichts Ähnliches wie die Antwort von Java auf SIGQUIT , daher müssen Sie es möglicherweise in Ihre Anwendung integrieren. Vielleicht könnten Sie einen Server in einem anderen Thread erstellen, der als Antwort auf eine Nachricht eine Stapelverfolgung erhält?
quelle
Verwenden Sie das Inspektionsmodul.
stack (context = 1) Gibt eine Liste von Datensätzen für den Stack über dem Frame des Aufrufers zurück.
Ich finde es sehr hilfreich.
quelle
In Python 3 installiert pdb automatisch einen Signalhandler, wenn Sie c (ont (inue)) zum ersten Mal im Debugger verwenden. Wenn Sie anschließend Strg-C drücken, werden Sie gleich wieder dort hineingelegt. In Python 2 ist hier ein Einzeiler, der auch in relativ alten Versionen funktionieren sollte (getestet in 2.7, aber ich habe die Python-Quelle auf 2.4 überprüft und es sah in Ordnung aus):
pdb lohnt sich zu lernen, wenn Sie viel Zeit mit dem Debuggen von Python verbringen. Die Benutzeroberfläche ist etwas stumpf, sollte aber jedem bekannt sein, der ähnliche Tools wie gdb verwendet hat.
quelle
Falls Sie dies mit uWSGI tun müssen, ist Python Tracebacker integriert, und es muss nur in der Konfiguration aktiviert werden (die Nummer ist an den Namen jedes Workers angehängt):
Sobald Sie dies getan haben, können Sie die Rückverfolgung drucken, indem Sie einfach eine Verbindung zum Socket herstellen:
quelle
An dem Punkt, an dem der Code ausgeführt wird, können Sie dieses kleine Snippet einfügen, um eine schön formatierte gedruckte Stapelverfolgung anzuzeigen. Es wird davon ausgegangen, dass Sie einen Ordner
logs
im Stammverzeichnis Ihres Projekts haben.quelle