Python: contextlib.redirect_stdout 有时不能实时工作

Python: contextlib.redirect_stdout sometimes doesn't work in real time

我在 Ubuntu 上使用 Python3.5。以下脚本创建一个文件 out 并用越来越多的行 "Hello":

填充它
import contextlib
with contextlib.redirect_stdout(open('out','w')):
    while True:
        print('Hello')

但是,如果我通过添加对 time.sleep() 的调用进行微小的修改,文件 out 将保持为空:

import contextlib
import time
with contextlib.redirect_stdout(open('out','w')):
    while True:
        print('Hello')
        time.sleep(1)

如果我通过将循环变成有限循环来进一步更改代码,它会填充 out,但只会在循环结束时形成一个块。

谁能重现并解释一下?

我打赌之前有人问过这个问题,但我找不到合适的副本。

这是由输出缓冲引起的。当 stdout 进入终端时,它是行缓冲的,这意味着每次遇到 "\n" 时,输出都会从您的程序发送到终端。但是当 stdout 引用一个文件时,它是块缓冲的。这意味着只有当缓冲区变满时(或当您明确刷新它或关闭句柄时)才会生成实际输出。

这是由输出缓冲引起的。这是一个使用 contextlib 的有趣案例,但潜在的问题是 open('out', 'w') 语句。

要防止输出缓冲,如果您使用 Python 2:

,可以将 buffering argument 设置为 0
import contextlib
import time

with contextlib.redirect_stdout(open('out','w', 0)):
    while True:
        print 'Hello'
        time.sleep(1)

或者,一旦上下文管理器关闭文件(或一旦缓冲内容超过一定大小),文件内容将被写入。

如果您使用的是 Python 3,则不能使用无缓冲文本 I/O(请在评论中指出)。但是,在每个循环结束时刷新 stdout 应该会产生预期的效果:

import contextlib
import time
import sys

with contextlib.redirect_stdout(open('out','w')):
    while True:
        print('Hello')
        sys.stdout.flush()
        time.sleep(1)