Anzeigen des Stack-Trace einer laufenden Python-Anwendung


340

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:


315

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):

import code, traceback, signal

def debug(sig, frame):
    """Interrupt running process, and provide a python prompt for
    interactive debugging."""
    d={'_frame':frame}         # Allow access to frame object.
    d.update(frame.f_globals)  # Unless shadowed by global
    d.update(frame.f_locals)

    i = code.InteractiveConsole(d)
    message  = "Signal received : entering python shell.\nTraceback:\n"
    message += ''.join(traceback.format_stack(frame))
    i.interact(message)

def listen():
    signal.signal(signal.SIGUSR1, debug)  # Register handler

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:

    os.kill(pid, signal.SIGUSR1)

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 .


1
Vielen Dank! Das ist genau das, wonach ich gesucht habe. Vielleicht könnten Sie dieses Skript auch mit Pipe-Unterstützung auf einer Python-Snippets-Site veröffentlichen?
Seb

2
Ich habe es jetzt auf der Python-Kochbuch-Website veröffentlicht - Link hinzugefügt.
Brian

1
Ich musste "Readline importieren" hinzufügen, um Verlaufsfunktionen zu aktivieren.
miracle2k

2
Toller Tipp! Dies funktioniert auch, um das Signal an alle Prozesse zu senden, die das Wort "mypythonapp" enthalten: pkill -SIGUSR1 -f mypythonapp
Alexander

10
Wenn die Anwendung nicht funktioniert, kann die Python-Interpreter-Schleife möglicherweise nicht ausgeführt werden, um das Signal zu verarbeiten. Verwenden Sie das faulthandlerModul (und seinen Backport auf PyPI) für einen C-Level-Signalhandler, der den Python-Stack druckt, ohne dass die Interpreter-Schleife reagieren muss.
GPS

146

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 ~/.gdbinitund dann:

  • Gdb anhängen: gdb -p PID
  • Holen Sie sich den Python-Stack-Trace: pystack

Es ist leider nicht ganz zuverlässig, aber es funktioniert die meiste Zeit.

Schließlich kann das Anhängen straceoft eine gute Vorstellung davon geben, was ein Prozess tut.


2
Brillant! Der Befehl pystack wird manchmal gesperrt, aber vorher gibt er mir eine vollständige Stapelverfolgung des Prozesses in Python-Codezeilen, ohne dass eine Vorbereitung erforderlich ist.
Muudscope

26
Kleinere Aktualisierung: Diese GDB-Technik (und der aktualisierte Code) sind unter wiki.python.org/moin/DebuggingWithGdb dokumentiert. Es gibt einige Entwicklungen in diesem Bereich, die unter dieser URL dokumentiert sind, und anscheinend hat GDB 7 Python-Unterstützung.
Nelson

7
Soweit ich das beurteilen kann, funktioniert dies nur dann wirklich, wenn Sie Debug-Symbole in Ihre Python-Binärdatei kompiliert haben - z. B.: Sie haben Ihr Programm mit python2-dbg ausgeführt (unter Ubuntu ist dies in einem separaten Paket enthalten python-dbg). Ohne diese Symbole scheinen Sie nicht viele nützliche Informationen zu erhalten.
Drevicko

1
in meinem Fall diese Rückkehr Unable to locate python framezu jedem Befehl
seriyPS

6
gdb 7+ --with-python wird von python-gdb.py unterstützt. Weitere Details hier: chezsoi.org/lucas/blog/2014/11/07/en-gdb-python-macros
Lucas Cimon

71

Ich 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 :

import threading, sys, traceback

def dumpstacks(signal, frame):
    id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
    code = []
    for threadId, stack in sys._current_frames().items():
        code.append("\n# Thread: %s(%d)" % (id2name.get(threadId,""), threadId))
        for filename, lineno, name, line in traceback.extract_stack(stack):
            code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
            if line:
                code.append("  %s" % (line.strip()))
    print "\n".join(code)

import signal
signal.signal(signal.SIGQUIT, dumpstacks)

53

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:

$ sudo pip install pyrasite
$ echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
$ sudo pyrasite 16262 dump_stacks.py # dumps stacks to stdout/stderr of the python program

(Hutspitze an @Albert, dessen Antwort unter anderem einen Zeiger darauf enthielt.)


5
Das hat dump_stacks.pyimport traceback; traceback.print_stack()
John Lehmann

2
traceback -lgibt Ihnen eine Liste vordefinierter Python-Skripte, die Sie verwenden können, und dump_stacks.pyist 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.
Johndodo

12
Wichtiger Tipp: Führen Sie 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!
Johndodo

Letzte Veröffentlichung von Pyrasit war im Jahr 2012
Boris

35
>>> import traceback
>>> def x():
>>>    print traceback.extract_stack()

>>> x()
[('<stdin>', 1, '<module>', None), ('<stdin>', 2, 'x', None)]

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:

import signal
import traceback

signal.signal(signal.SIGUSR1, lambda sig, stack: traceback.print_stack(stack))

zum Startcode in Ihrer Anwendung. Anschließend können Sie den Stapel drucken, indem Sie ihn SIGUSR1an den laufenden Python-Prozess senden .


2
Dies würde nur die Rückverfolgung des Hauptthreads drucken. Ich muss noch eine Lösung finden, um Spuren für alle Threads zu sehen. Tatsächlich scheint Python keine API zum Abrufen des Stapels vom Thread-Objekt zu haben, obwohl threading.enumerate () den Zugriff auf alle Thread-Objekte ermöglicht.
Haridsv

Dies funktioniert hervorragend auf Cygwin. Es werden zwar nur drei Zeilen der Stapelspur gedruckt, aber das reicht aus, um einen Hinweis zu erhalten
slashdottir

28

Das Traceback- Modul hat einige nette Funktionen, darunter: print_stack:

import traceback

traceback.print_stack()

1
Um den Stack-Trace in eine Datei zu schreiben, verwenden Sie: import traceback; f = open('/tmp/stack-trace.log', 'w') traceback.print_stack(file=f) f.close()
GuruM

1
+1 an @gulgi für seine benutzerfreundliche Antwort. Einige der anderen Antworten sahen für meine einfache Aufgabe, Call-Stack-Trace von der Funktion eines Skripts abzurufen, sehr kompliziert aus.
GuruM

24

Sie können das Faulthandler-Modul ausprobieren . Installieren Sie es mit pip install faulthandlerund fügen Sie hinzu:

import faulthandler, signal
faulthandler.register(signal.SIGUSR1)

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


20

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 PyEval_EvalFramezuPyEval_EvalFrameEx[bearbeiten: nicht mehr benötigt; Die verknüpfte Datei hat diese Änderung bereits ab dem 14.01.2010]

  • Gdb anhängen: gdb -p PID

  • Holen Sie sich den Python-Stack-Trace: pystack


Das gdbinit unter der genannten URL scheint bereits den von Ihnen vorgeschlagenen Patch zu haben. In meinem Fall hing meine CPU beim Tippen von Pystack einfach. Nicht sicher warum.
Jesse Glick

2
Nein, das tut es nicht - ich war unklar, sorry, weil diese Zeile an drei Stellen erscheint. Der Patch, den ich verlinkt habe, zeigt, welchen ich geändert habe, als ich diese Arbeit gesehen habe.
Gunnlaugur Briem

2
Wie bei der Antwort von @ spiv muss das Programm unter Python ausgeführt werden, das mit Debugging-Symbolen kompiliert wurde. Sonst bekommst du nurNo symbol "co" in current context.
Nickolay

12

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):

import traceback
import sys
def dumpstacks(signal, frame):
    code = []
    for threadId, stack in sys._current_frames().items():
            code.append("\n# Thread: %d" % (threadId))
        for filename, lineno, name, line in traceback.extract_stack(stack):
            code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
            if line:
                code.append("  %s" % (line.strip()))
    print "\n".join(code)

import signal
signal.signal(signal.SIGQUIT, dumpstacks)

11

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


Dies beantwortet die Frage nicht. Die Frage betraf einen bereits laufenden Prozess.
dbn

11

Schauen Sie sich das faulthandlerModul an, das neu in Python 3.3 ist. Ein faulthandlerBackport zur Verwendung in Python 2 ist auf PyPI verfügbar.


2
Eine neuere Antwort von @haypo behandelt dies ausführlicher. Ich bin nicht sicher, wie dies normalerweise auf SO gehandhabt wird, aber es fühlt sich falsch an, zwei im Wesentlichen doppelte Antworten zu haben ...
Nickolay

7

Unter Solaris können Sie pstack (1) verwenden. Es sind keine Änderungen am Python-Code erforderlich. z.B.

# pstack 16000 | grep : | head
16000: /usr/bin/python2.6 /usr/lib/pkg.depotd --cfg svc:/application/pkg/serv
[ /usr/lib/python2.6/vendor-packages/cherrypy/process/wspbus.py:282 (_wait) ]
[ /usr/lib/python2.6/vendor-packages/cherrypy/process/wspbus.py:295 (wait) ]
[ /usr/lib/python2.6/vendor-packages/cherrypy/process/wspbus.py:242 (block) ]
[ /usr/lib/python2.6/vendor-packages/cherrypy/_init_.py:249 (quickstart) ]
[ /usr/lib/pkg.depotd:890 (<module>) ]
[ /usr/lib/python2.6/threading.py:256 (wait) ]
[ /usr/lib/python2.6/Queue.py:177 (get) ]
[ /usr/lib/python2.6/vendor-packages/pkg/server/depot.py:2142 (run) ]
[ /usr/lib/python2.6/threading.py:477 (run)
etc.

2
Es scheint ein Debian / Ubuntu-Programm zu geben pstack, das dasselbe tut
Rory

1
Es scheint nur die Rückverfolgung unter Linux zu geben, nicht die Python-Rückverfolgung mit Dateinamen und Zeilennummern.
Ogrisel

6

Wenn Sie auf einem Linux-System arbeiten, nutzen Sie die Attraktivität von gdbPython-Debug-Erweiterungen (kann in python-dbgoder im python-debuginfoPaket enthalten sein). Es hilft auch bei Multithread-Anwendungen, GUI-Anwendungen und C-Modulen.

Führen Sie Ihr Programm aus mit:

$ gdb -ex r --args python <programname>.py [arguments]

Dies weist gdban, es vorzubereiten python <programname>.py <arguments>und zu rentfernen.

Wenn Sie das Programm hängen lassen, wechseln Sie in die gdbKonsole, drücken Sie Ctr+Cund führen Sie Folgendes aus:

(gdb) thread apply all py-list

Siehe Beispielsitzung und weitere Informationen hier und hier .


6

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 ():

import sys, traceback, signal
import threading
import os

def dumpstacks(signal, frame):
  id2name = dict((th.ident, th.name) for th in threading.enumerate())
  for threadId, stack in sys._current_frames().items():
    print(id2name[threadId])
    traceback.print_stack(f=stack)

signal.signal(signal.SIGQUIT, dumpstacks)

os.killpg(os.getpgid(0), signal.SIGQUIT)

Für meine Bedürfnisse filtere ich Threads auch nach Namen.


3

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 .


Scheint, als hätte es zwei ( 1 ) Umschreibungen ( 2 ) durchlaufen, ohne die von mir
Nickolay

3

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


1
Hinweis: Es ist nicht offensichtlich, wie dies erstellt werden soll. Vielen Dank für die Links, die Sie in README eingefügt haben: pyrasitehat perfekt funktioniert!
Nickolay

3

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_PIDist alles, was Sie tun müssen, um Aufrufstapel aller Threads im $SOME_PIDProzess 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.

$ sudo py-spy dump --pid 31080
Process 31080: python3.7 -m chronologer -e production serve -u www-data -m
Python v3.7.1 (/usr/local/bin/python3.7)

Thread 0x7FEF5E410400 (active): "MainThread"
    _wait (cherrypy/process/wspbus.py:370)
    wait (cherrypy/process/wspbus.py:384)
    block (cherrypy/process/wspbus.py:321)
    start (cherrypy/daemon.py:72)
    serve (chronologer/cli.py:27)
    main (chronologer/cli.py:84)
    <module> (chronologer/__main__.py:5)
    _run_code (runpy.py:85)
    _run_module_as_main (runpy.py:193)
Thread 0x7FEF55636700 (active): "_TimeoutMonitor"
    run (cherrypy/process/plugins.py:518)
    _bootstrap_inner (threading.py:917)
    _bootstrap (threading.py:885)
Thread 0x7FEF54B35700 (active): "HTTPServer Thread-2"
    accept (socket.py:212)
    tick (cherrypy/wsgiserver/__init__.py:2075)
    start (cherrypy/wsgiserver/__init__.py:2021)
    _start_http_thread (cherrypy/process/servers.py:217)
    run (threading.py:865)
    _bootstrap_inner (threading.py:917)
    _bootstrap (threading.py:885)
...
Thread 0x7FEF2BFFF700 (idle): "CP Server Thread-10"
    wait (threading.py:296)
    get (queue.py:170)
    run (cherrypy/wsgiserver/__init__.py:1586)
    _bootstrap_inner (threading.py:917)
    _bootstrap (threading.py:885)  

2

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.


3
Anscheinend ist es nicht kompatibel mit bestimmten GDB-Builds (z. B. dem, den ich auf Ubuntu installiert habe): github.com/google/pyringe/issues/16 , das manuell neu erstellt werden muss. Ein anderer Debugger pyrasitearbeitete für mich wie ein Zauber.
Nickolay

1

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.


1
Ja, das ist wahr. Es ist eine Schande, obwohl die pdb das Anhängen an einen laufenden Prozess nicht unterstützt ...
Bartosz Radaczyński

Das ist nicht wahr. Siehe die Antwort von "spiv" oben, die zeigt, wie man gdb verbindet und einen Python-Stack-Trace erhält.
Andrew Cooke

Es ist nicht dasselbe - diese GDB-Makros sind nicht zuverlässig und bieten nicht die volle Leistung / vertraute Schnittstelle von PDF. Ich wünschte oft, jemand hätte eine kleine App geschrieben, die ptrace verwendet, um Python-Bytecode in einen laufenden Python-Prozess einzufügen und 'import pdb' ausführen zu lassen. pdb.set_trace () ', möglicherweise auch nach vorübergehender Umleitung von sys.stdin / stdout.
Marius Gedminas

Dies ist nicht mehr wahr, siehe andere Antworten, die auf Pyringe / Pyrasit verweisen.
Nickolay

1

Sie können dazu PuDB verwenden , einen Python-Debugger mit einer Curses-Schnittstelle. Einfach hinzufügen

from pudb import set_interrupt_handler; set_interrupt_handler()

zu Ihrem Code und verwenden Sie Strg-C, wenn Sie brechen möchten. Sie können cmehrmals fortfahren und erneut brechen, wenn Sie es verpassen und es erneut versuchen möchten.


Wenn Sie den obigen Befehl in Django verwenden, vergessen Sie nicht, einen Server ordnungsgemäß auszuführen, um Störungen zu vermeiden: "manage.py runserver --noreload --nothreading"
potar

1

Ich bin im GDB-Camp mit den Python-Erweiterungen. Folgen Sie https://wiki.python.org/moin/DebuggingWithGdb , was bedeutet

  1. dnf install gdb python-debuginfo oder sudo apt-get install gdb python2.7-dbg
  2. gdb python <pid of running process>
  3. py-bt

Beachten Sie auch info threadsund thread apply all py-bt.


ist es normal , eine Antwort wie zu bekommen 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 Laufen py-btin gdb?
Crookedleaf

1
keine Ursache. Es liegt daran, dass meine App als lief sudo. Ich musste auch gdb pyton <pid>als Sudo laufen .
Crookedleaf

1

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.

>>> import pdb
>>> import my_function

>>> def f():
...     pdb.set_trace()
...     my_function()
... 

Rufen Sie dann die erstellte Funktion auf:

>>> f()
> <stdin>(3)f()
(Pdb) s
--Call--
> <stdin>(1)my_function()
(Pdb) 

Viel Spaß beim Debuggen :)


0

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?


0

Verwenden Sie das Inspektionsmodul.

import inspect help (inspect.stack) Hilfe zum Funktionsstapel im Modul inspect:

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.


0

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):

import pdb, signal
signal.signal(signal.SIGINT, lambda sig, frame: pdb.Pdb().set_trace(frame))

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.


0

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):

py-tracebacker=/var/run/uwsgi/pytrace

Sobald Sie dies getan haben, können Sie die Rückverfolgung drucken, indem Sie einfach eine Verbindung zum Socket herstellen:

uwsgi --connect-and-read /var/run/uwsgi/pytrace1

0

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 logsim Stammverzeichnis Ihres Projekts haben.

# DEBUG: START DEBUG -->
import traceback

with open('logs/stack-trace.log', 'w') as file:
    traceback.print_stack(file=file)
# DEBUG: END DEBUG --!
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.