2010-11-12 13 views
69

Voglio solo vedere lo stato del processo, è possibile collegare una console al processo, così posso richiamare funzioni all'interno del processo e vedere alcune delle le variabili globali.python: è possibile collegare una console in un processo in esecuzione

E 'meglio il processo è in esecuzione, senza l'influenza (di prestazioni corso può giù un po')

+7

quindi, in sostanza, un debugger? – st0le

+0

qualcosa come l'interprete della riga di comando python.exe –

+0

versione pdb: https://stackoverflow.com/questions/25308847/attaching-a-processo-con-pdb –

risposta

35

Se si ha accesso al codice sorgente del programma, è possibile aggiungere questa funzionalità in modo relativamente semplice.

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

Per citare:

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.


Un'altra implementazione di circa lo stesso concetto è fornito da rconsole. Dalla documentazione:

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

Questa è davvero una ricetta molto bella. Usare pipe e file per l'input e l'output è davvero intelligente e penso che qualsiasi progetto decente possa beneficiare di tale funzionalità. – erkmene

+2

Tuttavia, è molto insicuro, quindi usa con attenzione – fmark

+0

Ho provato la ricetta e ha rotto la mia installazione python. L'oggetto 'module' non ha attributo 'getmro' –

7

Perché non semplicemente utilizzando il modulo pdb? Ti consente di interrompere uno script, controllare i valori degli elementi ed eseguire il codice riga per riga. E poiché è basato sull'interprete Python, fornisce anche le funzionalità fornite dall'interprete classico. Per usarlo, basta mettere queste 2 righe nel codice, in cui si desidera interrompere e controllarla:

import pdb 
pdb.set_trace() 
+0

sai come avviarlo per un determinato thread di threading.enumerate()? – yucer

51

Ciò interromperà il processo (a meno che non si avvia in un thread), ma è possibile utilizzare il code modulo per avviare una console Python:

import code 
code.interact() 

Questo bloccherà fino a quando l'utente esce dalla console interattiva eseguendo exit().

Il modulo code è disponibile almeno in Python v2.6, probabilmente altri.

Tendo ad usare questo approccio in combinazione con i segnali per il mio lavoro su Linux (per Windows, vedi sotto). I schiaffo questo nella parte superiore del mio script Python:

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

E poi innescare da una shell con kill -SIGUSR2 <PID>, dove <PID> è l'ID del processo. Il processo si arresta quindi tutto ciò che sta facendo e presenta una console:

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

Generalmente da lì sarò caricare il componente lato server di un debugger remoto come l'eccellente WinPDB.

Windows non è un sistema operativo conforme allo POSIX e pertanto non fornisce gli stessi segnali di Linux. Tuttavia, Python v2.2 and above expose a Windows-specific signal SIGBREAK (attivato premendo CTRL + Pause/Break). Questo non interferisce con l'operazione normale CTRL + C (SIGINT) e quindi è un'alternativa pratica.

Pertanto un portatile, ma un po 'brutto, la versione di quanto sopra è:

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

I vantaggi di questo approccio:

  • Nessun moduli esterni (tutta roba standard di Python)
  • consuma a malapena qualsiasi risorsa fino a quando non viene attivata (2x importazione)

Ecco il codice che uso nel mio ambiente di produzione che caricherà il lato server di WinPDB (se disponibile) e ricadrà all'apertura di una console Python.

# 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

Puoi dare maggiori dettagli su come carichi il componente lato server di WinPDB una volta che hai una console Python? –

+1

Ho aggiunto il mio codice di produzione alla risposta, ma in sostanza è sufficiente inserire quanto segue in una console: '' importare rpdb2; rpdb2.start_embedded_debugger ("foobar", True, True) "" e quindi lancia la GUI WinPDB con password "foobar" quando richiesto – RobM

4

Un'altra possibilità, senza aggiungere roba per gli script python, è descritto qui:

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

Sfortunatamente, questa soluzione richiede anche qualche accortezza, almeno nella misura in cui è necessario essere usando una versione di Python con i simboli di debug in esso.

+0

Per la maggior parte delle distribuzioni Linux, python è costruito con simboli di debug, ma i simboli di debug risiedono in un pacchetto diverso. Il pacchetto di simboli di debug può essere installato dopo che lo script python è già stato avviato. –

14

Utilizzare pyrasite-shell. Non posso credere che funzioni così bene, ma è così. "Dagli un pid, prendi una 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' 

Questo lancia il guscio pitone con accesso alle variabili globali() e locali() variabili di quel processo in esecuzione pitone, e altre cose meravigliose.

Testato solo su Ubuntu, ma sembra anche per OSX.

Adattato da this answer.

Nota: la linea che disattiva la proprietà ptrace_scope è necessaria solo per i kernel/i sistemi che sono stati creati con CONFIG_SECURITY_YAMA attivo. Prenditi cura di ptrace_scope in ambienti sensibili perché potrebbe introdurre alcune vulnerabilità di sicurezza. Vedi here per i dettagli.

+0

@Dirk Credo che ptrace_scope sia essenziale per consentire a un processo di tracciare/interagire con un altro processo non correlato. – python1981

+0

Ovviamente questo è solo su sistemi che hanno YAMA. Proposta di modifica e rimosso il mio commento originale. (Anche questo per andare entro qualche tempo.) – Dirk

0

Utilizzando PyCharm, non riuscivo a connettermi al processo in Ubuntu. La soluzione per questo è disabilitare YAMA. Per maggiori informazioni vedi askubuntu

echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope 
Problemi correlati