如何在Python中检查是否启用了输出缓冲
如何检查Python中是否启用了输出缓冲?
在Linux上使用Python 3.8测试了stdout缓冲,发现Python3的输出缓冲可以检测是否在终端(TTY)上运行,如果是,则print函数的输出会立即显示,否则输出会延迟直到缓冲区满或脚本退出。例如,如果stdout被重定向到管道中,它将认为不是在终端上运行(对于Windows环境,不清楚会发生什么)。
当然,可以通过print函数的"flush=True"参数来防止输出延迟。还可以通过Python3的"-u"命令行参数禁用缓冲,或者通过设置shell环境变量PYTHONUNBUFFERED=true来禁用缓冲,这样缓冲区将被直接的FileIO所取代。
可以通过查询sys.stdout.buffer来检测所有这些情况,例如:
#!/usr/bin/env python3 import sys print("Name: ", type(sys.stdout.buffer).__name__) print("TTY? ", sys.stdout.buffer.isatty())
以下是此脚本在不同条件下的输出:
$ myscript.py # 立即显示 Name: BufferedWriter TTY? True $ myscript.py | tee # 因为管道而等待脚本退出 Name: BufferedWriter TTY? False $ python3 -u myscript.py # 立即显示 Name: FileIO TTY? True $ python3 -u myscript.py | tee # 尽管有管道,也会立即显示 Name: FileIO TTY? False
另外,还可以通过以下shebang来禁用缓冲(假设脚本名称在shell命令中没有以"python3"为前缀):
#!/usr/bin/env -S python3 -u
以上是如何检查Python中是否启用了输出缓冲的原因和解决方法。
文章标题:如何检查Python中是否启用了输出缓冲
在进行一些实验后,我找到了一种方法来区分Python是否在标准输出上进行了缓冲:
import sys def is_stdout_buffered(): # 打印一个空格和回车,但没有换行(不会有任何可见效果) print " \r", # 如果文件位置是一个正整数,则标准输出已经被缓冲 try: pos = sys.stdout.tell() if pos > 0: return True except IOError: # 在某些终端中,如果标准输出未被缓冲,tell()会抛出IOError pass return False
我只在Windows的CMD、MinGW和Git Bash中进行了测试。关键的测试是Git Bash,默认情况下是带有缓冲的,除非你使用`python -u`来调用它,这样它就是非缓冲的(参考链接:Cmd and Git bash have a different result when run a Python code)。
这个检查可以在终端脚本的开始处使用,以警告用户是否可能受到延迟输出的影响,例如来自print语句的输出如果没有刷新。
原因:在Python中,输出缓冲机制默认是开启的,这意味着当程序输出内容时,输出不会立即显示在终端上,而是先存储在缓冲区中,直到缓冲区满了或者程序执行结束后才会一次性输出到终端上。然而,有时我们希望能够实时地看到程序的输出,而不是等到程序执行完毕才显示。
解决方法:可以通过在终端中使用管道符号(|)来检查输出缓冲是否开启。具体步骤如下:
1. 打开终端,并进入到存放Python脚本的目录下。
2. 输入命令$ python myscript.py | cat
,其中myscript.py
是你的Python脚本文件名。
3. 如果输出是无缓冲的,脚本的输出会立即显示在终端上。否则,输出会被cat
命令缓冲,直到刷新发生,刷新可以由脚本触发,或者脚本执行完毕时触发。
通过这种方式,我们可以检查Python中的输出缓冲是否启用,以及实时地查看程序的输出。