为什么stdbuf对Python没有影响?

时间:2019-04-12 14:54:17

标签: python c linux pipe buffer

给出以下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在这里不起作用。

2 个答案:

答案 0 :(得分: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

(它是行缓冲的)

答案 1 :(得分:0)

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

  

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

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

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

  

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

由于Python明确指定了缓冲的详细信息,因此可以合理地期望它实际上可以肯定地管理其缓冲,从而消除stdbuf的影响。