如何检查Python是否启用了输出缓冲

5

在 Python 中有很多种关闭输出缓冲的方法:禁用输出缓冲

让我感到好奇的是,如何知道输出缓冲已经真正地关闭了?最简单和最好的检查方式是什么?


这真的很有趣。但我怀疑这是不可能的,因为sys是C模块,你不能做超出接口提供的事情。 - Dmitry Torba
也许有更简单的方法吗?如果打开或关闭它没有明显的区别,那我们就不用关心它了,对吧?可能需要一个GIF来解释。我甚至认为一张图片是不够的。 - Aminah Nuraini
1
不需要太在意,只要知道何时需要刷新,就可以调用 sys.stdout.flush(),无论缓冲是否开启都能正常工作。有些任务可能需要及时刷新,例如查看我的回答 http://stackoverflow.com/questions/39255498/python-cgi-os-system-causing-malformed-header ,但这并不意味着你需要知道数据是否被缓冲。这只是一个有趣的发现,但我认为在那种情况下你可以进行实验。 - Dmitry Torba
我知道。这是为了教育目的,因为我即将参加的一场考试强调输出缓冲的重要性。 - Aminah Nuraini
3个回答

2
尝试这个:$ python myscript.py | cat 如果是非缓冲的,则脚本输出会立即显示在终端上。否则,它将被cat缓冲,直到刷新发生,可以由脚本触发或者脚本完成时自动触发。

2
我已经在Linux上使用Python 3.8测试了stdout缓冲,并发现Python3的输出缓冲可以检测到它是否在终端(称为“TTY”)上运行,如果是,则打印函数的输出会立即显示,否则输出将延迟直到缓冲区满或脚本退出。例如,如果stdout被管道化,它将判断自己不在TTY上(抱歉,我不知道在Windows上会发生什么)。
当然,“flush=True”打印参数可以防止此输出延迟。也可以通过使用Python3的“-u”命令行参数禁用缓冲,或者通过设置shell环境变量PYTHONUNBUFFERED=true来防止输出延迟,在这种情况下,缓冲区将被直接的FileIO替换。
所有这些都可以通过查询sys.stdout.buffer在Python3中进行检测。
#!/usr/bin/env python3
import sys
print("Name: ", type(sys.stdout.buffer).__name__)
print("TTY? ", sys.stdout.buffer.isatty())

该脚本在不同条件下的输出如下:
$ myscript.py # Displays immediately
Name:  BufferedWriter
TTY?  True

$ myscript.py | tee # Waits for script exit because of pipe
Name:  BufferedWriter
TTY?  False

$ python3 -u myscript.py # Displays immediately
Name:  FileIO
TTY?  True

$ python3 -u myscript.py | tee # Also displays immediately despite pipe
Name:  FileIO
TTY?  False

编辑:如果脚本名称在shell命令中没有以“python3”为前缀,也可以使用以下shebang禁用缓冲。

#!/usr/bin/env -S python3 -u

1

经过一些实验,我发现这种方法可以区分Python是否在标准输出上进行缓冲:

import sys

def is_stdout_buffered():
    # Print a single space + carriage return but no new-line (should have no visible effect)
    print " \r",
    # If the file position is a positive integer then stdout is buffered
    try:
        pos = sys.stdout.tell()
        if pos > 0:
            return True
    except IOError:  # In some terminals tell() throws IOError if stdout is unbuffered
        pass
    return False

我只在Windows的CMD、MinGW和Git Bash上进行了测试。其中关键测试是Git Bash,它默认为缓冲模式,除非你使用python -u调用它,则为非缓冲模式(在运行Python代码时,Cmd和Git bash有不同的结果)。
这个检查可以在终端脚本开头使用,以警告用户如果没有刷新,则可能受到延迟输出的影响,例如来自print语句的输出。

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