将sys.stdout
替换为Tee logger(以将输出重定向到文件)之后,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()
有什么方法可以替换sys.stdout
而不破坏PDB?
答案 0 :(得分:0)
(1)您不能在发球区域的输出上具有交互性,因为它是常规流,而不是终端。终端可以做很多事情:定位光标,擦除内容,读取键,将按键回显到屏幕等。磁盘上的常规文件不能完成所有这些事情,这就是pdb
的原因无法以交互方式执行这些操作。您可以检查sys.stdout.isatty()
是否在运行REPL时返回True
。
(2)当然,您可以更改代码中的每个print
函数调用,以将stdout 和写入所需的任何文件,因为您可以重新定义print
。这在Python 3和Python 2.7(如果您from __future__ import print
中都有效)中有效。然后您可以执行以下操作:
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
声明,您的处境更糟。在macOS上使用strace
on Linux或DTrace
捕获到stdout(和其他地方)的写入,并在启动过程时将其重定向到文件:
strace -e trace=write -o writes.txt python your-script.py
它将把类似write(1, 'Hello world!')
的文件写入文件。您需要对其进行解析,然后将输出重构到stdout(1),以专门生成输出的真实副本。
我认为pdb
的交互模式也可以在此模式下工作;至少,Python REPL在strace下可以正常工作。