Python中的stdout在调用curses后未正确刷新

4 投票
4 回答
1236 浏览
提问于 2025-04-16 04:07

我有一个程序使用了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 调用之后进行的)。

撰写回答