2010-11-12 7 views
69

Solo quiero ver el estado del proceso, ¿es posible adjuntar una consola al proceso, así puedo invocar funciones dentro del proceso y ver algunas de las variables globales.python: es posible conectar una consola a un proceso en ejecución

Es mejor el proceso se está ejecutando sin ser afectado (rendimiento del curso puede bajar un poco)

+7

¿básicamente, un depurador? – st0le

+0

algo así como el intérprete de línea de comandos python.exe –

+0

versión pdb: https://stackoverflow.com/questions/25308847/attaching-a-process-with-pdb –

Respuesta

35

Si usted tiene acceso a código fuente del programa, puede agregar esta funcionalidad con relativa facilidad.

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

Para citar:

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.


Otra aplicación de más o menos el mismo concepto se proporciona por rconsole. A partir de la documentación:

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

Esa es realmente una muy buena receta. Usar pipas y archivos para entrada y salida es realmente inteligente y creo que cualquier proyecto decente se beneficiaría de tal funcionalidad. – erkmene

+2

Es muy inseguro, así que use con cuidado – fmark

+0

Probé la receta y rompió mi instalación de python. El objeto 'módulo' no tiene el atributo 'getmro' –

7

Por qué no simplemente utilizando el módulo pdb? Le permite detener un script, inspeccionar los valores de los elementos y ejecutar el código línea por línea. Y dado que está basado en el intérprete de Python, también proporciona las características proporcionadas por el intérprete clásico. Para usarlo, sólo hay que poner estas 2 líneas en su código, en el que desea detener e inspeccionar:

import pdb 
pdb.set_trace() 
+0

¿sabes cómo iniciarlo para un subproceso dado de threading.enumerate()? – yucer

51

Esto interrumpirá el proceso (a menos que se inicia en un hilo), pero se puede utilizar el code módulo para iniciar una consola Python:

import code 
code.interact() 

Esto bloqueará hasta que el usuario sale de la consola interactiva mediante la ejecución de exit().

El módulo code está disponible al menos en Python v2.6, probablemente en otros.

Tiendo a utilizar este enfoque en combinación con señales para mi trabajo con Linux (para Windows, ver a continuación). Bofetada esta en la parte superior de mis scripts de Python:

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

Y luego dispararlo desde un shell con kill -SIGUSR2 <PID>, donde <PID> es el ID del proceso. El proceso se detiene lo que está haciendo y presenta una consola:

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

general a partir de ahí voy a cargar el componente del lado del servidor de un depurador remoto como la excelente WinPDB.

Windows no es un sistema operativo compatible con POSIX, por lo que no proporciona las mismas señales que Linux. Sin embargo, Python v2.2 and above expose a Windows-specific signal SIGBREAK (activado presionando CTRL + Pause/Break). Esto hace que no interfiera con el funcionamiento normal de CTRL + C (SIGINT), por lo que es una alternativa práctica.

Por lo tanto un portátil, pero un poco fea, la versión de lo anterior es:

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

ventajas de este enfoque:

  • No hay módulos externos (todas las cosas estándar de Python)
  • consume apenas cualquier recurso hasta que se active (2x importación)

Este es el código que uso en mi entorno de producción que cargará el lado del servidor de WinPDB (si está disponible) y volverá a abrir una consola de 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

¿Puedes dar más detalles sobre cómo cargar el componente del servidor de WinPDB una vez que tienes una consola de Python? –

+1

He agregado mi código de producción a la respuesta, pero esencialmente solo necesita ingresar lo siguiente en una consola: '' import rpdb2; rpdb2.start_embedded_debugger ("foobar", True, True) '' y luego inicie la GUI de WinPDB con la contraseña "foobar" cuando se le solicite – RobM

4

Otra posibilidad, sin añadir cosas a los scripts de Python, se describe aquí:

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

Desafortunadamente, esta solución también requiere un poco de previsión, al menos en la medida en que tiene que ser usando una versión de python con símbolos de depuración en él.

+0

Para la mayoría de las distribuciones de Linux, python está construido con símbolos de depuración, pero los símbolos de depuración residen en un paquete diferente. El paquete de símbolos de depuración se puede instalar después de que su secuencia de comandos python ya se haya iniciado. –

14

Utilice pyrasite-shell. No puedo creer que funcione tan bien, pero lo hace. "Dale un pid, obtén un 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' 

Esto inicia el intérprete de Python con el acceso a las variables globales() y locales() variables de ese proceso de pitón en marcha, y otras cosas maravillosas.

Solo probado esto personalmente en Ubuntu, pero parece que también se ocupa de OSX.

Adaptado de this answer.

Nota: La línea que desconecta la propiedad ptrace_scope solo es necesaria para kernels/sistemas que se han creado con CONFIG_SECURITY_YAMA en. Tenga cuidado al jugar con ptrace_scope en entornos sensibles porque podría introducir ciertas vulnerabilidades de seguridad. Vea here para más detalles.

+0

@Dirk Creo que ptrace_scope es esencial para permitir que un proceso rastree/interactúe con otro proceso no relacionado. – python1981

+0

Obviamente, eso solo ocurre en los sistemas que tienen YAMA. Propuesta de edición y eliminó mi comentario original. (Este también para ir dentro de un tiempo). – Dirk

0

Usando PyCharm, me estaba fallando al conectarme al proceso en Ubuntu. La solución para esto es desactivar YAMA. Para obtener más información, vea askubuntu

echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope 
Cuestiones relacionadas