如何强制Python的print函数将缓冲输出刷新到屏幕?


另请参阅:如果目标是更改缓冲行为,则禁用输出缓冲。这个问题是关于在特定打印调用后显式刷新输出,即使输出仍在缓冲。

对于重复的闭包:如果初学者问了一个问题,试图在结尾处不使用换行符的情况下立即显示输出,请改用“当结尾处没有换行符时,为什么打印输出不立即显示在终端中?”?结束问题。目前的问题还不够好,因为提问者可能没有缓冲或冲洗的概念;另一个问题旨在首先解释这些概念,而这个问题是关于技术细节的。


当前回答

丹的想法不太奏效:

#!/usr/bin/env python
class flushfile(file):
    def __init__(self, f):
        self.f = f
    def write(self, x):
        self.f.write(x)
        self.f.flush()

import sys
sys.stdout = flushfile(sys.stdout)

print "foo"

结果:

Traceback (most recent call last):
  File "./passpersist.py", line 12, in <module>
    print "foo"
ValueError: I/O operation on closed file

我认为问题是它继承自file类,这实际上是不必要的。根据sys.stdout的文档:

stdout和stderr不必内置文件对象:可以接受任何对象只要它有write()方法这需要一个字符串参数。

所以改变

class flushfile(file):

to

class flushfile(object):

使其工作正常。

其他回答

这是我的版本,它也提供了writeline()和fileno():

class FlushFile(object):
    def __init__(self, fd):
        self.fd = fd

    def write(self, x):
        ret = self.fd.write(x)
        self.fd.flush()
        return ret

    def writelines(self, lines):
        ret = self.writelines(lines)
        self.fd.flush()
        return ret

    def flush(self):
        return self.fd.flush

    def close(self):
        return self.fd.close()

    def fileno(self):
        return self.fd.fileno()

使用-u命令行开关可以工作,但有点笨拙。这意味着如果用户在没有-u选项的情况下调用脚本,程序可能会出现错误行为。我通常使用自定义stdout,如下所示:

class flushfile:
  def __init__(self, f):
    self.f = f

  def write(self, x):
    self.f.write(x)
    self.f.flush()

import sys
sys.stdout = flushfile(sys.stdout)

…现在,所有打印调用(隐式使用sys.stdout)都将自动刷新。

在Python 3.x中,print()函数得到了扩展:

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

所以,你可以这样做:

print("Visiting toilet", flush=True)

Python文档条目

从Python 3.3开始,您可以强制普通的print()函数刷新,而无需使用sys.stdout.flush();只需将“flush”关键字参数设置为true。根据文档:

打印(*对象,sep=“”,end=“\n”,file=sys.stdout,flush=False)将对象打印到流文件中,以sep分隔,后跟end。sep、end和file(如果存在)必须作为关键字参数提供。所有非关键字参数都被转换为字符串,如str()所做,并被写入流中,以sep分隔,后跟end。sep和end都必须是字符串;它们也可以是None,这意味着使用默认值。如果没有给定对象,print()将只写结束。file参数必须是具有write(string)方法的对象;如果不存在或无,将使用sys.stdout。输出是否缓冲通常由文件决定,但如果flush关键字参数为true,则强制刷新流。

此外,正如这篇博文中所建议的,可以在无缓冲模式下重新打开sys.stdout:

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

每个stdout.write和打印操作之后都会自动刷新。