用 Tee 记录器替换sys.stdout
(将输出重定向到文件)后,PDB 不再正常工作。例如,按向上箭头将生成^[[A
而不是上一个命令。
可以使用以下代码片段重现该问题:
import sys
import pdb
class Tee(object):
def __init__(self, name, mode):
self.file = open(name, mode)
self.stdout = sys.stdout
sys.stdout = self
def __del__(self):
sys.stdout = self.stdout
self.file.close()
def write(self, data):
self.file.write(data)
self.stdout.write(data)
def flush(self):
self.file.flush()
sys.stdout = Tee('test.txt', 'w')
pdb.set_trace()
有没有办法在不破坏 PDB 的情况下替换sys.stdout
?
(1) 您不能在 tee'd 输出上进行交互,因为它是常规流,而不是终端。终端允许做很多事情:定位光标,擦除内容,读取按键,将按键回显到屏幕上等。磁盘上的常规文件无法执行所有这些操作,这就是为什么pdb
无法在交互模式下执行这些操作的原因。您可以检查sys.stdout.isatty()
是否返回True
您是否正在运行 REPL 。
(2)当然,您可以更改代码中的每个print
函数调用以写入stdout和所需的任何文件,因为您可以重新定义print
。这适用于 Python 3,如果您from __future__ import print
,则适用于 Python 2.7 。然后你可以做这样的事情:
system_print = print # preserve the original.
def print_also_to(other_file):
def tee_print(*args, **kwargs):
system_print(*args, **kwargs) # Normally prints to stdout.
system_print(*args, **kwargs, file=other_file) # Write a copy.
return tee_print
print = print_also_to(open('/tmp/copy-of-stdout')) # A crude example.
print("Hello world!") # Unmodified code.
有了print
陈述,你的情况会更糟。在 Linux 上使用strace
或在 macOS 上使用DTrace
捕获对 stdout(和其他地方)的写入,并在启动进程时将其重定向到文件:
strace -e trace=write -o writes.txt python your-script.py
它会向文件写入类似write(1, 'Hello world!')
.您需要解析它并将输出重建为 stdout (1) 以生成输出的真实副本。
我想pdb
的交互模式也可以在此下工作;至少,Python REPL 在 strace 下工作得很好。