How to attach debugger to a python subproccess?

前端 未结 8 2275
旧巷少年郎
旧巷少年郎 2020-12-22 23:49

I need to debug a child process spawned by multiprocessing.Process(). The pdb degugger seems to be unaware of forking and unable to attach to alrea

相关标签:
8条回答
  • 2020-12-23 00:22

    An idea I had was to create "dummy" classes to fake the implementation of the methods you are using from multiprocessing:

    from multiprocessing import Pool
    
    
    class DummyPool():
        @staticmethod
        def apply_async(func, args, kwds):
            return DummyApplyResult(func(*args, **kwds))
    
        def close(self): pass
        def join(self): pass
    
    
    class DummyApplyResult():
        def __init__(self, result):
            self.result = result
    
        def get(self):
            return self.result
    
    
    def foo(a, b, switch):
        # set trace when DummyPool is used
        # import ipdb; ipdb.set_trace()
        if switch:
            return b - a
        else:
            return a - b
    
    
    if __name__ == '__main__':
        xml = etree.parse('C:/Users/anmendoza/Downloads/jim - 8.1/running-config.xml')
        pool = DummyPool()  # switch between Pool() and DummyPool() here
        results = []
        results.append(pool.apply_async(foo, args=(1, 100), kwds={'switch': True}))
        pool.close()
        pool.join()
        results[0].get()
    
    0 讨论(0)
  • 2020-12-23 00:27

    This is an elaboration of Romuald's answer which restores the original stdin using its file descriptor. This keeps readline working inside the debugger. Besides, pdb special management of KeyboardInterrupt is disabled, in order it not to interfere with multiprocessing sigint handler.

    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
    
    0 讨论(0)
  • 2020-12-23 00:29

    Here is the version of the ForkedPdb(Romuald's Solution) which will work for Windows and *nix based systems.

    import sys
    import pdb
    import win32console
    
    
    class MyHandle():
        def __init__(self):
            self.screenBuffer = win32console.GetStdHandle(win32console.STD_INPUT_HANDLE)
        
        def readline(self):
            return self.screenBuffer.ReadConsole(1000)
    
    class ForkedPdb(pdb.Pdb):
        def interaction(self, *args, **kwargs):
            _stdin = sys.stdin
            try:
                if sys.platform == "win32":
                    sys.stdin = MyHandle()
                else:
                    sys.stdin = open('/dev/stdin')
                pdb.Pdb.interaction(self, *args, **kwargs)
            finally:
                sys.stdin = _stdin
    
    
    0 讨论(0)
  • 2020-12-23 00:32

    I've been searching for a simple to solution for this problem and came up with this:

    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
    

    Use it the same way you might use the classic Pdb:

    ForkedPdb().set_trace()
    
    0 讨论(0)
  • 2020-12-23 00:33

    Winpdb is pretty much the definition of a smarter Python debugger. It explicitly supports going down a fork, not sure it works nicely with multiprocessing.Process() but it's worth a try.

    For a list of candidates to check for support of your use case, see the list of Python Debuggers in the wiki.

    0 讨论(0)
  • 2020-12-23 00:37

    If you are on a supported platform, try DTrace. Most of the BSD / Solaris / OS X family support DTrace.

    Here is an intro by the author. You can use Dtrace to debug just about anything.

    Here is a SO post on learning DTrace.

    0 讨论(0)
提交回复
热议问题