在 python 中杀死标准输出会中断 get_line_buffer()

Killing stdout in python breaks get_line_buffer()

所以我正在使用一些库(不幸的是,这让我很懊恼)打印到标准输出以获得某些调试信息。好的,没问题,我只是禁用了它:

import sys,os
sys.stdout = open(os.devnull,'wb')

我最近添加了用于在终端中获取用户输入和打印输出的代码,这当然需要 stdout。但同样,没问题,而不是 print 我可以这样做:

sys.__stdout__.write('text\n')

最后,因为我在一个单独的线程中执行 raw_input 并且程序的输出可能会打断用户的输入,所以我想按照 in the first part of this answer 所述重新回显测试以使其更或使用 readline.get_line_buffer() 不太无缝。例如,如果用户输入 foobar:

> foobar

然后另一个线程说 Interrupting text! 它应该看起来像:

Interrupting text!
> foobar

但我观察到:

Interrupting text!
>

事实证明 readline.get_line_buffer() 始终为空,并且代码无法重新回应用户键入的内容。如果我删除 sys.stdout 覆盖,一切都会按预期工作(除了现在库的调试输出未被阻止)。

如果重要的话,我在 Linux 上使用 Python 2.7。也许我想做的是不可能的,但我真的很想知道为什么会这样。在我看来,用 stdout 做事不应该影响 stdin 行缓冲区,但我承认不熟悉底层库或实现。

下面是一个最低限度的工作示例。只需键入内容并等待中断文本。提示 "> " 将被重新回显,但您输入的文本不会。只需注释掉第二行即可看到它是否正常工作。当线程打印时,它将行缓冲区记录到 stdin.log.

import time,readline,thread,sys,os
sys.stdout = open(os.devnull,'wb')  # comment this line!

def noisy_thread():
  while True:
    time.sleep(5)
    line = readline.get_line_buffer()
    with open('stdin.log','a') as f:
      f.write(time.asctime()+' | "'+line+'"\n')
    sys.__stdout__.write('\r'+' '*(len(line)+2)+'\r')
    sys.__stdout__.write('Interrupting text!\n')
    sys.__stdout__.write('> ' + line)
    sys.__stdout__.flush()

thread.start_new_thread(noisy_thread, ())
while True:
    sys.__stdout__.write('> ')
    s = raw_input()

我也在 get_line_buffer() 调用之前尝试了 sys.stdout = sys.__stdout__,但这也不起作用。非常感谢任何帮助或解释。

当您重定向标准输出时,raw_input() 停止工作。 如果您在 raw_input() 之前尝试 sys.stdout = sys.__stdout__ 它会再次起作用。 stdinstdout 都需要连接到终端才能使 raw_input 工作。