在python中杀死stdout会破坏get_line_buffer()

时间:2016-09-19 16:42:21

标签: python multithreading stdout raw-input

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

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()

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

1 个答案:

答案 0 :(得分:1)

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