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

如何检查Python中是否启用了输出缓冲,python,python-2.7,output,buffer,output-buffering,Python,Python 2.7,Output,Buffer,Output Buffering,在Python中,有很多方法可以关闭输出缓冲: 让我好奇的是,我怎么知道输出缓冲真的已经关闭了?最简单的检查方法是什么?试试这个:$python myscript.py | cat 如果未缓冲,脚本的输出将立即显示在终端上。否则,它将被cat缓冲,直到刷新发生,或者由脚本触发,或者在刷新完成时。经过一些实验后,我发现这种方法可以区分python是否在标准输出上缓冲: import sys def is_stdout_buffered(): # Print a single space

在Python中,有很多方法可以关闭输出缓冲:


让我好奇的是,我怎么知道输出缓冲真的已经关闭了?最简单的检查方法是什么?

试试这个:
$python myscript.py | cat


如果未缓冲,脚本的输出将立即显示在终端上。否则,它将被
cat
缓冲,直到刷新发生,或者由脚本触发,或者在刷新完成时。

经过一些实验后,我发现这种方法可以区分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
我只在CMD、MinGW和gitbash中的Windows上测试过它。关键测试是gitbash,它默认为buffered,除非您使用
python-u
调用它,在这种情况下它是unbuffered()


此检查可在终端脚本开始时用于警告用户是否可能受到延迟输出的影响,例如,如果没有刷新,则来自打印语句。

我已使用Python 3.8在Linux上测试了标准输出缓冲区,发现Python 3的输出缓冲区可以检测它是否在终端上运行(“TTY”),在这种情况下,打印功能的输出将立即显示,否则输出将延迟,直到缓冲区已满或脚本退出。例如,如果stdout通过管道传输,它将决定它不在TTY。(对不起,我不知道Windows上会发生什么。)

当然,使用“flush=True”打印参数可以防止这种输出延迟。还可以通过使用Python3的“-u”命令行参数禁用缓冲,或者通过设置shell环境变量PYTHONUNBUFFERED=true来防止这种情况,在这种情况下,缓冲区将替换为直接文件IO

所有这些都可以通过查询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
编辑:也可以使用以下shebang禁用缓冲(假设脚本名称在shell命令中没有前缀“python3”)


这真的很有趣。但是我怀疑这是可能的,因为
sys
是C模块,除了界面提供的功能之外,您不能做太多。也许有更简单的功能?如果打开或关闭它,我们会得到什么明显的区别?如果没有区别,我们就不在乎了,对吗?可能需要GIF来解释。我甚至不认为一张图片就足够了。真的,没有必要在意。只要知道何时需要刷新,就可以调用
sys.stdout.flush()
,无论缓冲是打开还是关闭都可以正常工作。有些任务可能需要及时刷新,例如查看我的答案,但您不需要知道数据是否已缓冲。这是一个有趣的发现,但我认为在这种情况下,你可以做一个实验。我知道。这是出于教育目的,因为我要参加的一次测试强调了输出缓冲的重要性
#!/usr/bin/env -S python3 -u