2010-11-12 2 views
69

Ich möchte nur den Zustand des Prozesses zu sehen, ist es möglich, eine Konsole in den Prozess anhängen, damit ich Funktionen innerhalb des Prozesses aufrufen und einige sehen kann die globalen Variablen.Python: ist es möglich, eine Konsole in einem laufenden Prozess anfügen

Es ist besser, der Prozess läuft ohne (natürlich Leistung ein wenig kann nach unten)

+7

also im Grunde ein Debugger? – st0le

+0

etwas wie der Kommandozeilen-Interpreter python.exe –

+0

pdb-Version: https://StackOverflow.com/Questions/25308847/attaching-a-Process-with-Pdb –

Antwort

35

beeinträchtigt werden, wenn Sie den Zugriff auf die Programmquelle-Code haben, können Sie diese Funktionalität hinzufügen können relativ leicht.

Siehe Recipe 576515: Debugging a running python process by interrupting and providing an interactive prompt (Python)

zu zitieren:

This provides code to allow any python program which uses it to be interrupted at the current point, and communicated with via a normal python interactive console. This allows the locals, globals and associated program state to be investigated, as well as calling arbitrary functions and classes.

To use, a process should import the module, and call listen() at any point during startup. To interrupt this process, the script can be run directly, giving the process Id of the process to debug as the parameter.


Eine weitere Implementierung von etwa dem gleichen Konzept wird durch rconsole zur Verfügung gestellt. Aus der Dokumentation:

rconsole is a remote Python console with auto completion, which can be used to inspect and modify the namespace of a running script.

To invoke in a script do:

from rfoo.utils import rconsole 
rconsole.spawn_server() 

To attach from a shell do:

$ rconsole 

Security note: The rconsole listener started with spawn_server() will accept any local connection and may therefore be insecure to use in shared hosting or similar environments!

+2

Das ist wirklich ein sehr schönes Rezept. Die Verwendung von Pipes und Dateien für die Eingabe und Ausgabe ist wirklich clever und ich denke, jedes anständige Projekt würde von einer solchen Funktionalität profitieren. – erkmene

+2

Es ist sehr unsicher, aber mit Vorsicht verwenden – fmark

+0

Ich versuchte Rezept und es brach meine Python-Installation. 'Modul' Objekt hat kein Attribut 'getmro' –

7

Warum nicht einfach die pdb Modul? Es ermöglicht Ihnen, ein Skript zu stoppen, Elemente Werte zu inspizieren und den Code Zeile für Zeile auszuführen. Und da es auf dem Python-Interpreter basiert, bietet es auch die Funktionen des klassischen Interpreters. Um es zu nutzen, setzen Sie einfach diese 2 Zeilen im Code, in dem Sie es stoppen und zu überprüfen:

import pdb 
pdb.set_trace() 
+0

Wissen Sie, wie Sie es für einen bestimmten Thread von threading.enumerate() starten? – yucer

51

Dies wird Ihren Prozess unterbrechen (wenn Sie es in einem Thread starten), aber Sie können die code verwenden Modul eine Python-Konsole zu starten:

import code 
code.interact() 

Dies blockiert, bis der Benutzer durch Ausführen exit() die interaktive Konsole beendet.

Das Modul code ist in mindestens Python v2.6, wahrscheinlich anderen, verfügbar.

Ich neige dazu, diesen Ansatz in Kombination mit Signalen für meine Linux-Arbeit zu verwenden (für Windows, siehe unten). Ich schlage dies an der Spitze meines Python-Skripte:

import code 
import signal 
signal.signal(signal.SIGUSR2, lambda sig, frame: code.interact()) 

Und dann auslösen aus einer Schale mit kill -SIGUSR2 <PID>, wo <PID> die Prozess-ID ist. Der Prozess stoppt dann, was es tut, und stellt eine Konsole:

Python 2.6.2 (r262:71600, Oct 9 2009, 17:53:52) 
[GCC 3.4.2] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
(InteractiveConsole) 
>>> 

Allgemeinen von dort ich die serverseitige Komponente laden werden von einem Remote-Debugger wie das ausgezeichnete WinPDB.

Windows ist kein POSIX -kompatibles Betriebssystem und bietet daher nicht die gleichen Signale wie Linux. Python v2.2 and above expose a Windows-specific signal SIGBREAK (ausgelöst durch Drücken von CTRL + Pause/Break). Dies tut nicht interferieren mit normalen CTRL + C (SIGINT) Betrieb, und so ist eine handliche Alternative.

daher ein tragbarer, aber etwas hässlich, Version der oben ist:

import code 
import signal 
signal.signal(
     vars(signal).get("SIGBREAK") or vars(signal).get("SIGUSR2"), 
     lambda sig, frame: code.interact() 
     ) 

Vorteile dieses Ansatzes:

  • Keine externe Module (alle Standard-Python-Sachen)
  • kaum verbraucht beliebige Ressourcen bis zum Auslösen (2x Import)

Hier ist der Code, den ich in meiner Produktionsumgebung verwende, der die Server-Seite von WinPDB lädt (falls verfügbar) und auf das Öffnen einer Python-Konsole zurückgreift.

# Break into a Python console upon SIGUSR1 (Linux) or SIGBREAK (Windows: 
# CTRL+Pause/Break). To be included in all production code, just in case. 
def debug_signal_handler(signal, frame): 
    del signal 
    del frame 

    try: 
     import rpdb2 
     print 
     print 
     print "Starting embedded RPDB2 debugger. Password is 'foobar'" 
     print 
     print 
     rpdb2.start_embedded_debugger("foobar", True, True) 
     rpdb2.setbreak(depth=1) 
     return 
    except StandardError: 
     pass 

    try: 
     import code 
     code.interact() 
    except StandardError as ex: 
     print "%r, returning to normal program flow" % ex 

import signal 
try: 
    signal.signal(
      vars(signal).get("SIGBREAK") or vars(signal).get("SIGUSR1"), 
      debug_signal_handler 
      ) 
except ValueError: 
    # Typically: ValueError: signal only works in main thread 
    pass 
+0

Können Sie mehr Details darüber geben, wie Sie die serverseitige Komponente von WinPDB laden, sobald Sie eine Python-Konsole haben? –

+1

Ich habe meinen Produktionscode zur Antwort hinzugefügt, aber im Wesentlichen müssen Sie nur Folgendes an einer Konsole eingeben: '' import rpdb2; rpdb2.start_embedded_debugger ("foobar", True, True) "" und dann die GUI von WinPDB mit dem Passwort "foobar" starten – RobM

4

Eine andere Möglichkeit, ohne Material zu den Python-Skripte hinzugefügt wird, wird hier beschrieben:

https://wiki.python.org/moin/DebuggingWithGdb

Leider ist diese Lösung erfordert auch eine gewisse Umsicht, dass Sie zumindest in dem Maße sein müssen Verwenden einer Version von Python mit Debugging-Symbolen darin.

+0

Bei den meisten Linux-Distributionen wird Python mit Debugging-Symbolen gebaut, aber die Debugging-Symbole befinden sich in einem anderen Paket. Das Debugging-Symbolpaket kann installiert werden, nachdem das Python-Skript bereits gestartet wurde. –

14

Verwenden Sie pyrasite-shell. Ich kann nicht glauben, dass es so gut funktioniert, aber es tut es. "Geben Sie ihm eine Pid, ​​erhalten Sie eine Shell".

$ sudo pip install pyrasite 
$ echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope # If YAMA activated, see below. 
$ pyrasite-shell 16262 
Pyrasite Shell 2.0 
Connected to 'python my_script.py' 
Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
[GCC 4.8.2] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 

>>> globals() 
>>> print(db_session) 
>>> run_some_local_function() 
>>> some_existing_local_variable = 'new value' 

Dadurch wird der Python-Shell mit Zugang zu den Globals() und Einheimischen() Variablen des laufenden Python-Prozess, und andere wunderbare Dinge.

Habe das nur persönlich auf Ubuntu getestet, scheint aber auch OSX zu bedienen.

Angepasst von this answer.

Hinweis: Die Zeile, die die Eigenschaft ptrace_scope ausschaltet, ist nur für Kernel/Systeme erforderlich, die mit CONFIG_SECURITY_YAMA erstellt wurden. Passen Sie auf, dass Sie in sensiblen Umgebungen mit ptrace_scope herumhantieren, da dies zu gewissen Sicherheitslücken führen kann. Details finden Sie unter here.

+0

@Dirk Ich glaube, ptrace_scope ist wichtig, damit ein Prozess mit einem anderen nicht verwandten Prozess verfolgen/interagieren kann. – python1981

+0

Offensichtlich ist das nur auf Systemen, die YAMA haben. Vorgeschlagene Bearbeitung und entfernte meinen ursprünglichen Kommentar. (Dieser auch innerhalb einiger Zeit zu gehen.) – Dirk

0

Mit PyCharm konnte ich keine Verbindung zum Prozess in Ubuntu herstellen. Der Fix dafür ist, YAMA zu deaktivieren. Weitere Informationen finden Sie unter askubuntu

echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope 
Verwandte Themen