我试图找到一种方法将remote_pdb和entr一起用作快速测试和开发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。
我要求的是:
我接受一个提供命令行解决方案的答案,该解决方案结合了entr
和remote_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套接字和进程组有关。我相应地添加了标签。
答案 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_pdb
和hunter
的作者ionelmc慷慨帮助追踪问题。