我希望我没有遗漏任何重要的事情,但你似乎不能以一种完全微不足道的方式做到这一点,因为
readline
只有在
pdb.Pdb
(分别。
cmd.Cmd
use_rawinput
设置为非零,但会导致忽略
stdin
以及为调试器和脚本本身混合输入。也就是说,到目前为止,我能想到的最好的办法是:
#!/usr/bin/env python3
import os
import sys
import pdb
pdb_inst = pdb.Pdb()
stdin_called = os.fdopen(os.dup(0))
console_new = open('/dev/tty')
os.dup2(console_new.fileno(), 0)
console_new.close()
sys.stdin = os.fdopen(0)
for line in stdin_called:
pdb_inst.set_trace()
sys.stdout.write(line)
它对您的原始脚本是相对侵入性的,即使它至少可以放在它的外部并导入、调用或用作包装器。
STDIN
到一个文件描述符并以
stdin_called
/dev/tty
用于读取,替换了进程的文件描述符
0
(用于
标准物质
;它应该使用返回的值
sys.stdin.fileno()
)有了这个,我刚刚打开并重新分配了一个对应的类文件对象
sys.stdin
. 这样程序循环
pdb
pdb公司
与看起来只是一个“普通”控制台进行交互
标准物质
它很高兴能够
打开。
阅读线
(行编辑、历史记录、完成)输入时
pdb公司
$ { echo one; echo two; } | python3 cat.py
> /tmp/so/cat.py(16)<module>()
-> sys.stdout.write(line)
(Pdb) c
one
> /tmp/so/cat.py(15)<module>()
-> pdb_inst.set_trace()
(Pdb) con[TAB][TAB]
condition cont continue
(Pdb) cont
two
注意,从3.7版开始,您可以使用
breakpoint()
而不是
import pdb; pdb.Pdb().set_trace()
dup2
调用以确保按预期创建/替换文件描述符。
import sys
# Add this: BEGIN
import os
import pdb
import inspect
pdb_inst = pdb.Pdb()
class WrapSys:
def __init__(self):
self.__stdin = os.fdopen(os.dup(0))
self.__console = open('/dev/tty')
os.dup2(self.__console.fileno(), 0)
self.__console.close()
self.__console = os.fdopen(0)
self.__sys = sys
def __getattr__(self, name):
if name == 'stdin':
if any((f.filename.endswith("pdb.py") for f in inspect.stack())):
return self.__console
else:
return self.__stdin
else:
return getattr(self.__sys, name)
sys = WrapSys()
# Add this: END
for line in sys.stdin:
pdb_inst.set_trace() # Inject breakpoint
sys.stdout.write(line)
我一路都没挖过,但事实上,
pdb公司
cmd
似乎不仅需要
也可以使用fd
为了
阅读线
sys
代表为了预设不同的含义
标准输入
当代码来自
pdb.py
在堆栈上。一个明显的警告。如果还有其他的话
也期望并依赖于
标准输入
fd将成为
0个
,它仍然是不走运的(或者从另一个流读取它的输入,如果它只是为了它)。