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

时间:2019-07-05 18:55:19

标签: python pdb

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?

1 个答案:

答案 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 LinuxDTrace捕获到stdout(和其他地方)的写入,并在启动过程时将其重定向到文件:

strace -e trace=write -o writes.txt python your-script.py

它将把类似write(1, 'Hello world!')的文件写入文件。您需要对其进行解析,然后将输出重构到stdout(1),以专门生成输出的真实副本。

我认为pdb的交互模式也可以在此模式下工作;至少,Python REPL在strace下可以正常工作。