2011-01-17 24 views
20

Necesito depurar un proceso hijo engendrado por multiprocessing.Process(). El degugger pdb parece desconocer bifurcaciones y no se puede conectar a procesos que ya se están ejecutando.¿Cómo adjuntar el depurador a un subproceso de python?

¿Hay depuradores de python más inteligentes que se puedan unir a un subproceso?

Respuesta

9

Winpdb es prácticamente la definición de un depurador de Python más inteligente. Es explícitamente compatible con going down a fork, no estoy seguro si funciona bien con multiprocessing.Process(), pero vale la pena intentarlo.

Para obtener una lista de los candidatos que verifican el soporte de su caso de uso, consulte la lista de Python Debuggers en la wiki.

+1

Genial! Winpdb funciona bien con multiprocessing.Process() – grep

+0

Cabe señalar que Winpdb es un software gratuito, multiplataforma y gratuito. – OliverUv

+0

No pude, en 20 minutos de leer y jugar con winpdb, encontrar una manera de simplemente iniciar una sesión de depuración interactiva en un script existente a través de una importación, a la 'import pdb; pdb.set_trace() '. Sin embargo, la respuesta de ForkedPdb funcionaba como un amuleto. – Pat

35

He estado buscando un simple solución para este problema y se acercó con esto:

import sys 
import pdb 

class ForkedPdb(pdb.Pdb): 
    """A Pdb subclass that may be used 
    from a forked multiprocessing child 

    """ 
    def interaction(self, *args, **kwargs): 
     _stdin = sys.stdin 
     try: 
      sys.stdin = open('/dev/stdin') 
      pdb.Pdb.interaction(self, *args, **kwargs) 
     finally: 
      sys.stdin = _stdin 

usarlo de la misma manera que usted puede utilizar el clásico Pdb:

ForkedPdb().set_trace() 
+4

esto es asombroso e hizo el truco para mí –

+0

Gracias, esto funcionó para mí también. – xamox

+0

Buen truco. Sugiero almacenar sys.stdin cuando el programa se inicie y usarlo en el proceso bifurcado en lugar de abrir '/ dev/stdin'. No sé la razón, pero readline funciona bien entonces. Voy a investigar un poco sobre esto más tarde. – memeplex

2

Este es una elaboración de la respuesta de Romuald que restaura el stdin original usando su descriptor de archivo. Esto mantiene readline trabajando dentro del depurador. Además, la administración especial de pdb de KeyboardInterrupt está deshabilitada, para que no interfiera con el controlador multiproceso sigint.

class ForkablePdb(pdb.Pdb): 

    _original_stdin_fd = sys.stdin.fileno() 
    _original_stdin = None 

    def __init__(self): 
     pdb.Pdb.__init__(self, nosigint=True) 

    def _cmdloop(self): 
     current_stdin = sys.stdin 
     try: 
      if not self._original_stdin: 
       self._original_stdin = os.fdopen(self._original_stdin_fd) 
      sys.stdin = self._original_stdin 
      self.cmdloop() 
     finally: 
      sys.stdin = current_stdin 
Cuestiones relacionadas