【问题标题】:Why doesn't `readline` return for `subprocess.stdout`?为什么 `subprocess.stdout` 的`readline` 不返回?
【发布时间】:2021-01-08 03:10:01
【问题描述】:

我使用 Python subprocess fork 一个 C 应用程序并打开一个到 stdout 的管道。

app = subprocess.Popen(args, stdout=subprocess.PIPE)

应用程序向stdout 写入几行,如下所示:

printf("Line 0\n");
printf("Line 1\n");
printf("Line 2\n");

我尝试在应用程序退出之前在我的 Python 脚本中读取这些行:

line = app.stdout.readline()

然而,readline 会无限期地阻塞而不返回任何内容,即使我希望在对readline 的三个单独调用中读取Line 0Line 1Line 2。我注意到当应用程序最终退出时,readline 返回预期的内容。但是,我希望readline 在传递给printf 后立即返回预期的内容。发生了什么?

【问题讨论】:

    标签: python subprocess printf stdout


    【解决方案1】:

    根据this StackOverflow questionprintf 仅在输出设备是交互式的(例如终端)时将其输出刷新到换行符上。 当输出设备是非交互的(例如,Python子进程管道、文件等)时,stdout是完全缓冲的,所以只有在缓冲区满时才会刷新输出,当fflush(stdout)被手动调用,或者当缓冲区被强制刷新时(例如,在进程退出时)。

    因此,readline 没有返回,因为应用程序的 stdout 从未刷新,因此 readline 没有可读取的内容。将应用程序代码更改为此可以解决问题:

    printf("Line 0\n");
    printf("Line 1\n");
    printf("Line 2\n");
    fflush(stdout);  // New line
    

    其他人不妨用setvbuf设置stdout的缓冲模式,而不是调用fflush

    我对此感到惊讶,因为对printf 的普遍理解是它刷新换行符,但并非在所有情况下都会发生这种情况。

    【讨论】:

    • 我认为您的答案中混淆了“非交互式”和“交互式”。 “交互式”是指终端; “非交互式”是指管道。
    • 不仅调用fflush();如果它退出。程序没有退出是一个可能应该包含在问题中的细节。
    • @jamesdlin 不错!固定。
    猜你喜欢
    • 1970-01-01
    • 2019-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-06
    • 1970-01-01
    • 2017-10-08
    • 2014-04-21
    相关资源
    最近更新 更多