【问题标题】:Why stdbuf has no effect on Python?为什么 stdbuf 对 Python 没有影响?
【发布时间】:2019-09-03 09:07:44
【问题描述】:

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

【问题讨论】:

  • 来自man stdbuf 注意:如果 COMMAND 调整其标准流的缓冲(例如,'tee' 会这样做),那么它将覆盖由 'stdbuf' 更改的相应设置。还有一些过滤器(如 'dd' 和 'cat' 等)不使用流进行 I/O,因此不受 'stdbuf' 设置的影响。 我猜python 正在这样做。跨度>

标签: python c linux pipe buffer


【解决方案1】:

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

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

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

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

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

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

【讨论】:

    【解决方案2】:

    看起来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
    

    (而且它是行缓冲的)

    【讨论】:

    • 你是我的英雄
    猜你喜欢
    • 2013-01-18
    • 1970-01-01
    • 1970-01-01
    • 2019-09-28
    • 1970-01-01
    • 2015-02-08
    • 2016-08-19
    • 2018-06-04
    • 1970-01-01
    相关资源
    最近更新 更多