Python中的stdout在调用curses后未正确刷新
我有一个程序使用了curses库,然后又返回到主脚本进行进一步处理。返回后,我后续输出到标准输出(stdout)的内容,直到有大量数据(比如几千字节)才会显示出来。
我把这个问题简化成一个非常简单的程序,结果总是出错:
import curses
import time
curses.initscr()
curses.endwin()
print "Hello world!"
time.sleep(5)
如果我把两个curses的调用注释掉,'Hello world!'会在延迟之前打印出来。如果我把它们放上去,它就会在延迟之后(也就是脚本结束时)才打印出来。
4 个回答
1
更清晰的方式:
import sys
import curses
correct_stdout = sys.stdout # remember correct
curses.initscr()
curses.endwin()
sys.stdout = correct_stdout # restore correct
1
亚历克斯比我先做到了(他知道,我得自己琢磨),不过我写了一个很不错的上下文管理器,你可能会用得上。
import curses
import time
import os
import sys
class CursesStdout(object):
def __enter__(self):
pass
def __exit__(self, *args):
sys.stdout = sys.__stdout__ = os.fdopen(sys.__stdout__.fileno(), 'w', 0)
with CursesStdout():
curses.initscr()
curses.endwin()
print "Hello world!"
time.sleep(2)
我直接修改了 sys.__stdout__
,因为当你查看 curses/__init__.py
的源代码时,会发现 initscr
函数把那个文件描述符传给了C代码,所以我把它存起来,以便之后可以恢复到正常状态。
3
curses.endwin()
这个调用是用来“把标准输入输出恢复正常”的……但不幸的是,这里的“正常”指的是“缓冲的”(你可以把这个看作是 curses
的一个 bug,并在 Python 的问题追踪系统上报告这个问题)。
为了确保标准输出是无缓冲的,
import os
sys.stdout = os.fdopen(0, 'w', 0)
(你可以把 import os
放在开头,当然;重新赋值 sys.stdout
是在 endwin
调用之后进行的)。