为什么stdbuf对Python没有影响?

问题描述 投票:2回答:2

给出Python中的以下程序:

import sys

print("input")
while True:
    pass

和C中的等价物:

#include <stdio.h>

int main() {
        printf("input\n");
        while(1);
        return 0;
}

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

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

% ./a.out | cat
(empty)

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

% stdbuf -oL ./a.out | cat
input

但这不适用于Python:

% stdbuf -oL python3 a.py | cat
(empty)

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

python c linux pipe buffer
2个回答
2
投票

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

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

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

程序可以控制自己的缓冲,因为stdbuf的文件承认:

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

由于Python明确指定了缓冲细节,因此可以合理地预期它实际上肯定地管理它的缓冲,从而扼杀了stdbuf的任何效果。


0
投票

看起来python决定是否使用基于isatty的缓冲。

我用过这个脚本(来自Trick an application into thinking its stdout is a terminal, not a pipe):

faketty() {
    script -qfc "$(printf "%q " "$@")" /dev/null
}

它有效:

% faketty python3 a.py | cat
input

(并且它是行缓冲的)

© www.soinside.com 2019 - 2024. All rights reserved.