Frage

Ich habe diese Python-Anwendung, die von Zeit zu Zeit stecken bleibt und ich kann nicht herausfinden, wo.

Gibt es eine Möglichkeit Python-Interpreter zu signalisieren Sie den genauen Code zu erhalten, die ausgeführt wird?

Eine Art on-the-fly Stacktrace?

ähnliche Fragen:

War es hilfreich?

Lösung

Ich habe Modul I für Situationen wie diese verwenden - wo ein Prozess für eine lange Zeit ausgeführt wird, sondern wird manchmal aus unbekannten und nicht nachvollziehbaren Gründen stecken. Es ist ein bisschen hacky und funktioniert nur auf 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

zu verwenden, rufen Sie einfach die Funktion listen () zu einem bestimmten Zeitpunkt, wenn Ihr Programm startet (Sie selbst es in site.py halten konnte alle Python-Programme es verwenden haben), und laufen lassen. An jedem Punkt, senden Sie den Prozess ein SIGUSR1 Signal, zu töten, oder in Python:

    os.kill(pid, signal.SIGUSR1)

Dies führt dazu, dass das Programm zu einem Python-Konsole es wird derzeit an dem Punkt zu brechen, können Sie den Stack-Trace zeigt, und lassen Sie die Variablen manipulieren. Verwenden Steuer-d (EOF) weiter ausgeführt werden (obwohl beachten Sie, dass Sie wahrscheinlich jeden E / A usw. unterbrechen an dem Punkt, Sie signalisieren, so dass es nicht vollständig nicht-intrusive ist.

ich ein anderes Skript habe, die die gleiche Sache tut, außer es mit dem laufenden Prozess durch ein Rohr in Verbindung steht (zum Debuggen von backgrounded Prozessen usw. ermöglichen). Es ist ein bisschen groß, um hier zu posten, aber ich habe es als Python Kochbuch Rezept hinzugefügt.

Andere Tipps

Der Vorschlag, einen Signal-Handler zu installieren, ist ein guter, und ich benutze es viel. Zum Beispiel Bzr standardmäßig installiert eine SIGQUIT-Handler, der pdb.set_trace() sofort ruft euch in eine pDB aufzufordern. (Siehe bzrlib.breakin Quelle des Moduls für die genauen Details.) Mit pdb können Sie nicht nur die aktuelle Stack-Trace erhalten, sondern auch Variablen überprüfen, usw.

Aber manchmal brauche ich einen Prozess zu debuggen, dass ich nicht die Weitsicht in den Signal-Handler installiert habe. Unter Linux Sie gdb an den Prozess und einen Python-Stack-Trace mit einigen gdb Makros anhängen. Setzen Sie http://svn.python.org/projects/python/trunk/Misc/ gdbinit in ~/.gdbinit, dann:

  • Anhängen GDB: gdb -p PID
  • Holen Sie sich das Python-Stack-Trace: pystack

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

Schließlich strace Befestigung kann oft geben Ihnen eine gute Vorstellung davon, was ein Prozess tut.

Ich bin fast immer mit mehreren Threads und Hauptthread zu tun tut im Allgemeinen nicht viel, so was ist höchst interessant ist es, alle Stapel zu entleeren (was eher wie die Java-Dump). Hier ist eine Implementierung auf Basis von diesem Blog :

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)

Wie Sie einen Stack-Trace eines unvorbereitet Python-Programm, laufen in einem Lager Python ohne Debugging-Symbole mit pyrasite . Arbeitete wie ein Charme für mich auf Ubuntu Trusty:

$ 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 zu @Albert, dessen Antwort einen Zeiger auf diese enthalten sind, unter anderen Werkzeugen.)

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

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

Sie können auch gut die Stack-Trace-Format finden Sie in der docs .

Bearbeiten : Java Verhalten zu simulieren, wie sie durch @Douglas Leeder vorgeschlagen, fügen Sie diese:

import signal
import traceback

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

auf den Startcode in Ihrer Anwendung. Dann können Sie den Stapel drucken, indem SIGUSR1 zum laufenden Python-Prozess zu senden.

Die Traceback Modul hat einige schöne Funktionen, darunter: print_stack:

import traceback

traceback.print_stack()

Sie können versuchen, das faulthandler Modul . Installieren Sie es mit pip install faulthandler und fügen Sie:

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

am Anfang des Programms. Dann senden Sie SIGUSR1 an Ihren Prozess (ex: kill -USR1 42) auf die Standardausgabe des Python-Traceback aller Threads angezeigt werden soll. Lesen Sie die Dokumentation für mehr Optionen (zB: log in eine Datei) und andere Möglichkeiten, um die Rückverfolgung anzuzeigen.

Das Modul ist nun Teil von Python 3.3. Für Python 2 finden Sie unter http://faulthandler.readthedocs.org/

Was mich hier wirklich geholfen ist spiv < aus einem Stack-Trace für das erhalten eines unvorbereitet Python-Prozess / a> (was ich wählen würde und kommentieren, wenn ich die Rating-Punkte habe). Außer es hat nicht funktioniert, bis ich die gdbinit Skript geändert . Also:

Python -dv yourscript.py

Das wird der Interpreter macht im Debug-Modus laufen und Ihnen eine Spur zu geben, was der Dolmetscher tut.

Wenn Sie den Code interaktiv debuggen, sollten Sie es wie folgt aus:

python -m pdb yourscript.py

Das sagt das Python-Interpreter das Skript mit dem Modul „PDB“ laufen, die der Python-Debugger ist, wenn Sie es so, dass der Interpreter ausgeführt wird im interaktiven Modus ausgeführt werden, ähnlich wie GDB

Werfen Sie einen Blick auf dem faulthandler Modul, neu in Python 3.3 . Ein faulthandler Rückportierung für den Einsatz in Python 2 ist auf PyPI zur Verfügung.

Unter Solaris können Sie pstack (1) Nachträgliche Änderungen an den Python-Code sind nötig. zB.

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

Wenn Sie auf einem Linux-System sind, verwenden Sie das awesomeness von gdb mit Python Debug-Erweiterungen (kann in python-dbg oder python-debuginfo Paket sein). Es hilft auch bei Multi-Thread-Anwendungen, GUI-Anwendungen und C-Modulen.

Führen Sie Ihr Programm mit:

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

Das weist gdb python <programname>.py <arguments> vorzubereiten und run es.

Wenn Sie nun hängt programmieren, schalten Sie in gdb Konsole, drücken Sie Strg + C und ausführen:

(gdb) thread apply all py-list

Siehe Beispiel Sitzung und weitere Informationen hier und hier .

Ich war auf der Suche für eine Weile für eine Lösung meiner Threads zu debuggen und ich finde es hier dank haridsv. Ich verwende etwas vereinfachte Version unter Verwendung des 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 ich auch Themen filtern nach Namen.

Es ist lohnt einen Blick auf Pydb „, eine erweiterte Version der Python-Debugger auf dem losen basieren gDB-Befehlssatz“. Es umfasst Signal Manager, die Pflege des Startens des Debuggers nehmen kann, wenn ein bestimmtes Signal gesendet wird.

A 2006 Summer of Code Projekt sah Remote-Debugging-Funktionen auf dem Hinzufügen eines Moduls pydb a href = namens < "http://svn.python.org/projects/sandbox/trunk/pdb/" rel = "nofollow noreferrer "> mpdb .

gehackt ich einige Werkzeug zusammen, die in einem laufenden Python-Prozess misst und spritzt einen Code ein Python-Shell zu erhalten.

Sehen Sie hier: https://github.com/albertz/pydbattach

pyringe ist ein Debugger, der mit laufenden Python-Prozesse, Print Stack-Traces, Variablen interagieren können, usw. ohne a priori-Setup.

Während ich oft die Signal-Handler-Lösung in der Vergangenheit verwendet habe, kann es immer noch oft schwierig sein, das Problem in bestimmten Umgebungen zu reproduzieren.

Es gibt keine Möglichkeit, in einen laufenden Python-Prozess anzuschließen und vernünftige Ergebnisse zu erzielen. Was ich tun, wenn Prozesse einsperren ist strace in Einhaken und versuchen, herauszufinden, was genau passiert ist.

Leider oft strace ist der Beobachter, dass „fixe“ Rennbedingungen, so dass der Ausgang auch nutzlos ist.

Sie können PuDB , ein Python-Debugger mit einer Flüche Schnittstelle, dies zu tun. Fügen Sie einfach

from pudb import set_interrupt_handler; set_interrupt_handler()

, um Ihren Code und drücken Sie Strg-C, wenn Sie brechen wollen. Sie können mit c weiter und brechen wieder mehrmals, wenn Sie es versäumen und noch einmal versuchen möchten.

Wie debuggen jede Funktion in der Konsole :

Erstellen Funktion , wo Sie Verwendung pdb.set_trace () , dann funktionieren Sie debuggen möchten.

>>> import pdb
>>> import my_function

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

Dann erstellt Funktion aufrufen:

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

Happy-Debugging:)

Ich weiß nicht, von etwas ähnlich wie java Antwort auf SIGQUIT rel="nofollow , so könnten Sie es in Ihrer Anwendung zu bauen. Vielleicht könnten Sie einen Server in einem anderen Thread machen, die eine stacktrace auf Antwort auf eine Nachricht von einer Art bekommen können?

verwenden Sie das Modul überprüfen.

  
    
      

Import inspizieren       Hilfe (inspect.stack)       Hilfe auf Funktion Stapel in Modul überprüfen:

    
  

Stapel (context = 1)     Gibt eine Liste von Datensätzen für den Stapel oberhalb des Rahmens des Anrufers.

Ich finde es in der Tat sehr hilfreich.

In Python 3, PDB wird automatisch ein Signal-Handler Sie das erste Mal c (ont (inue)) in dem Debugger installieren. Durch Drücken von Strg-C danach werden Sie sich zurück in dort ab. In Python 2, hier ist ein Einzeiler, die in relativ alten Versionen arbeiten, auch sollten (getestet in 2.7, aber ich überprüfte Quelle Python zurück auf 2,4 und es sah in Ordnung):

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

PDB lohnt sich das Lernen, wenn Sie jede Menge Zeit Python Debuggen verbringen. Die Schnittstelle ist ein bisschen stumpf, sollte aber für jeden, der verwendet hat ähnliche Werkzeuge, wie gdb vertraut sein.

Im Fall, dass Sie dies mit uwsgi zu tun, es hat Python Tracebacker eingebaut und es ist nur Materie ermöglicht es in der Konfiguration (Nummer an den Namen für jeden Arbeitnehmer gebunden ist):

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

Sobald Sie dies getan haben, können Sie einfach ausdrucken Backtrace durch an die Buchse anschließen:

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

Ich bin in der GDB Lager 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

Sehen Sie sich auch info threads und thread apply all py-bt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top