【发布时间】:2017-01-27 10:24:17
【问题描述】:
所以我正在使用一些库(不幸的是,这让我很懊恼)打印到标准输出以获取某些调试信息。好的,没问题,我只是禁用了它:
import sys,os
sys.stdout = open(os.devnull,'wb')
我最近添加了用于在终端中获取用户输入和打印输出的代码,这当然需要标准输出。但同样,没问题,我可以这样做,而不是 print:
sys.__stdout__.write('text\n')
最后,由于我在单独的线程中执行 raw_input 并且程序的输出可能会中断用户输入,因此我想按照 in the first part of this answer 的描述重新回显测试,以使其或多或少地使用 @987654326 无缝@。例如,如果用户输入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__,但这也不起作用。非常感谢任何帮助或解释。
【问题讨论】:
-
我会向这些库发送拉取请求以使用
logging,因为从库代码打印到 stdout 或 stderr 是荒谬的。或者至少提交一个错误报告。也许名字和耻辱:P -
我也刚刚写了一个快速包装类,似乎任何替换
stdout的东西都会破坏 readline 行为。 -
谢谢,我确实这样做了,但与此同时,我仍然很想知道为什么会发生这种情况:)
-
是的,我同意这是一个超级奇怪的问题。
标签: python multithreading stdout raw-input