Python PDB 交互模式在重定向 sys.stdout 时中断



用 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 下工作得很好。

最新更新