Python调用curses后,标准输出无法正确刷新

4

我有一个使用curses的程序,然后返回到主脚本进行进一步处理。在它返回后,我的后续标准输出不会出现,直到有大量内容(例如数千字节)。

我已将问题简化为一个非常简单的程序,可以可靠地失败:

import curses
import time

curses.initscr()
curses.endwin()

print "Hello world!"
time.sleep(5)

如果我注释掉这两个curses调用,'Hello world!'会在延迟之前打印出来。如果我把它们放进去,它会在延迟之后打印出来(当脚本退出时)。

可能是如何刷新Python print的输出?的重复问题。 - Jack
@jack。不是的。这与为什么需要首先刷新输出缓冲区有关。 - aaronasterling
好的,抱歉。只是试图帮助指向可以帮助的东西! - Jack
4个回答

3
curses.endwin()函数会“将标准I/O设置回正常状态”,但不幸的是这意味着“带缓冲区”(您可以认为这是库中的一个漏洞,并在Python跟踪器上报告此问题)。
为确保标准输出是无缓冲的,请执行以下操作:
import os

sys.stdout = os.fdopen(0, 'w', 0)

你可以在开头放置 import os,当然;将 sys.stdout 的重新赋值放在 endwin 调用之后。


那么标准输出的生命开始时是无缓冲的吗?我原以为这就是 -u 标志的作用。但是是的,这个修复办法有效,谢谢。 - Neil Baylis
“将标准 I/O 设置回正常状态”具体指什么?我在 Python 文档、curses 模块源代码或 endwin man 页面(curs_initscr(3X))中都没有看到相关说明。 - jwelsh

1
更清晰的方式:

更清晰的说明:

import sys
import curses

correct_stdout = sys.stdout    # remember correct

curses.initscr()
curses.endwin()

sys.stdout = correct_stdout    # restore correct

1
Alex比我先做到了这件事(他知道,我还得想出来),但我写了这个巧妙的上下文管理器,你可能会用得上。
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代码,所以我存储它以便恢复正常。


这也很好,但我不能使用它,因为这个项目是在Python 2.4上的。不过还是谢谢。 - Neil Baylis

0

我发现这取决于系统/库。在我的Windows机器上(从http://www.lfd.uci.edu/~gohlke/pythonlibs/下载的curses),它会刷新然后休眠,但在Linux上,它会在休眠后刷新。我认为你可以简单地使用:sys.stdout.flush(),如下:

print "Hello world!"
sys.stdout.flush()
time.sleep(5)

(可能更好的做法是制作一种“打印和刷新”函数)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接