为什么 stdbuf 对 Python 没有影响?

Max*_*amy 7 c python linux buffer pipe

给定以下 Python 程序:

import sys

print("input")
while True:
    pass
Run Code Online (Sandbox Code Playgroud)

和 C 中的等价物:

#include <stdio.h>

int main() {
        printf("input\n");
        while(1);
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

当我使用管道cat传输程序时,默认情况下输出是缓冲的(而不是行缓冲的)。结果,我没有输出:

% python3 ./a.py | cat
(empty)

% ./a.out | cat
(empty)
Run Code Online (Sandbox Code Playgroud)

我可以stdbuf用来切换回行缓冲:

% stdbuf -oL ./a.out | cat
input
Run Code Online (Sandbox Code Playgroud)

但这不适用于 Python:

% stdbuf -oL python3 a.py | cat
(empty)
Run Code Online (Sandbox Code Playgroud)

知道为什么吗?我知道存在python3 -u但我想要行缓冲,而不是“无缓冲”,我希望这个命令行也适用于其他语言。该命令unbuffer似乎也有效,但我想了解为什么stdbuf在这里不起作用。

Joh*_*ger 7

默认情况下,Python 的print()函数将其输出定向到sys.stdout,其文档指定了以下内容:

当互动,stdoutstderr流是行缓冲。否则,它们像常规文本文件一样被块缓冲。您可以使用-u命令行选项覆盖此值。

请注意,这些文档并没有为一般环境影响留出空间,例如stdbuf命令的缓冲模式sys.stdout:如果使用该-u选项(或等效地,如果PYTHONUNBUFFERED设置了环境变量),则它是无缓冲的,否则行-如果交互式则缓冲,如果非交互式则缓冲。

程序可以控制自己的缓冲,正如stdbuf确认的文档:

注意:如果 COMMAND 调整其标准流的缓冲(例如 'tee' 就是这样做的),那么这将覆盖由 'stdbuf' 更改的相应设置。此外,某些过滤器(如“dd”和“cat”等)不使用 I/O 流,因此不受“stdbuf”设置的影响。

由于 Python 明确指定了缓冲细节,因此可以合理地期望它实际上确实肯定地管理其缓冲,从而对stdbuf.