2016-09-19 93 views
4

因此,我使用了一些库(不幸的是,很多我的烦恼)打印到某些调试信息的标准输出。用于获取用户输入和输出印刷在终端上,这当然需要标准输出在Python中杀死标准输出get_line_buffer()

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

我最近添加代码:好的,没问题,我只是禁用它。但同样,没有任何问题,而不是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()呼叫前右,但也不管用。任何帮助或解释非常感谢。

+0

我会发送一个拉请求到那些库来代替使用'logging',因为从库代码打印到stdout *或* stderr是荒谬的。或者至少提交一个错误报告。也许名字和耻辱:P –

+0

我也只写了一个快速包装类,它似乎代替'stdout'的任何东西都会破坏readline行为。 –

+0

谢谢,我确实这么做了,但同时我还是很想知道_why_这是怎么回事:) – TheSchwa

回答

1

它的raw_input()在重定向stdout时停止工作。 如果您在raw_input()之前尝试sys.stdout = sys.__stdout__,它会再次运行。 需要将stdinstdout连接到终端,以使raw_input能够正常工作。

+0

现在你已经说过它有多大意义,只是无法为自己工作。谢谢! – TheSchwa