为什么 `readline` return 不用于 `subprocess.stdout`?

Why doesn't `readline` return for `subprocess.stdout`?

我使用 Python subprocess 分叉一个 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 会无限期地阻止 return 任何内容,即使我希望阅读 Line 0Line 1Line 2,对 readline 的三个单独调用。我注意到当应用程序最终退出时,readline return 是预期的内容。但是,我希望 readline 到 return 预期的内容一旦传递给 printf。发生了什么事?

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

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

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

其他人可能希望用setvbuf设置stdout的缓冲模式而不是调用fflush.

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