调试在

时间:2017-05-06 17:44:20

标签: python macos pdb python-sockets

我试图找到一种方法将remote_pdbentr一起用作快速测试和开发Python 3多处理应用程序的环境,但它们并没有很好地发挥作用在一起。

考虑下面的简单测试用例:

import time
from multiprocessing import Process
from remote_pdb import RemotePdb
def child():
    RemotePdb('localhost', 4444).set_trace()
    while True:
        print("I am the child")
        time.sleep(1)
proc = Process(target=child)
proc.start()
proc.join()

如果我将其保存在文件中,比如说,' mp.py'并运行它:

python mp.py

它非常好用。正如预期的那样,它会在显示的子进程中中断

CRITICAL:root:RemotePdb session open at 127.0.0.1:4444, waiting for connection ...
RemotePdb session open at 127.0.0.1:4444, waiting for connection ... 

我可以从另一个终端会话与netcat或socat连接并使用python调试器。退出调试器会使子节点和父节点一直运行,直到我明确地终止它们为止。

如果我现在注释掉RemotePdb()调用并使用

entr的控制下运行脚本
ls mp.py | entr -r python mp.py

它允许我编辑mp.py并在每次保存时自动清理重启。

当我取消注释RemotePdb()调用时出现问题。

脚本由entr重新启动,它会在显示相同“等待连接”的孩子中断。消息和以前一样,但是如果我尝试在另一个终端窗口中与netcat连接,则pdb会话没有响应,没有输出,也没有回声 - 只有空行响应CR&#39}。我使用socat得到了相同的结果。

我在OS X 10.11.6上开发了python 3.5.3,entr 3.7,remote_pdb 1.2。

我要求的是: 我接受一个提供命令行解决方案的答案,该解决方案结合了entrremote_pdb的好处,或者明确解释了为什么无法完成。

谢谢!

更新 进一步测试表明,问题的-r(重启)选项是产生问题所必需的,即

ls mp.py | entr python mp.py

允许调试器连接工作。不幸的是,重启选项对于工作流程至关重要。

更新2 :问题似乎与设置进程组有关。这是由entr -r完成的,以确保可以杀死所有子进程。在尝试使用Python脚本替换entr时,我发现如果从IPython启动脚本,在父进程中调用os.setpgrp()将产生相同的失败(没有调试器的I / O) shell(!python mp.py)但不是从bash启动。

更新3 :我和remote_pdb的作者已经独立验证了Linux中没有出现此问题。这是一个OS X问题,显然与Python套接字和进程组有关。我相应地添加了标签。

1 个答案:

答案 0 :(得分:0)

解决!这是一个旧的OS X python问题,无论是悄悄进入还是从未在Pdb中修复过。修复是在导入readline之前设置忽略SIGTTOU。有关详细信息,请参阅http://bugs.python.org/issue14892

我通过修补pdb.Pdb的本地副本来解决问题,如下所示。

class Pdb(bdb.Bdb, cmd.Cmd):

    _previous_sigint_handler = None

    def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None,
                 nosigint=False):
        bdb.Bdb.__init__(self, skip=skip)
        cmd.Cmd.__init__(self, completekey, stdin, stdout)
        if stdout:
            self.use_rawinput = 0
        self.prompt = '(Pdb) '
        self.aliases = {}
        self.displaying = {}
        self.mainpyfile = ''
        self._wait_for_mainpyfile = False
        self.tb_lineno = {}
        # Try to load readline if it exists
        try:
############ FIX OSX BUG ######################################
            import sys
            if sys.platform == 'darwin':
                import signal
                signal.signal(signal.SIGTTOU, signal.SIG_IGN)
############ END FIX ##########################################
            import readline
            # remove some common file name delimiters
            readline.set_completer_delims(' \t\n`@#$%^&*()=+[{]}\\|;:\'",<>?')
        except ImportError:
            pass               

非常感谢remote_pdbhunter的作者ionelmc慷慨帮助追踪问题。