管道时在python的子进程模块中使用stdout.close()

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了管道时在python的子进程模块中使用stdout.close()相关的知识,希望对你有一定的参考价值。

在python子进程模块中,如果我们想运行shell命令

foo | grep bar

从python中,我们可能会使用

p1 = Popen(["foo"], stdout = PIPE)
p2 = Popen(["grep", "bar"], stdin = p1.stdout, stdout = PIPE)
p1.stdout.close()
output = p2.communicate()[0]

我对p1.stdout.close()线感到困惑。如果你原谅我,我将追溯我认为该程序是如何工作的,并且错误将有希望揭示出来。

在我看来,当线条output = p2.communicate()[0]由python制定时,python试图调用p2,它认识到它需要来自p1的输出。所以它调用p1,它执行foo并将输出抛出到堆栈上,以便p2可以完成执行。然后p2完成。

但是在这个痕迹中没有任何地方确实发生了p1.stdout.close()。那么实际发生了什么?在我看来,这种行的排序也可能很重要,所以以下方法不起作用:

p1 = Popen(["foo"], stdout = PIPE)
p1.stdout.close()
p2 = Popen(["grep", "bar"], stdin = p1.stdout, stdout = PIPE)
output = p2.communicate()[0]

这就是我的理解状态。

答案

p1.stdout.close()foo检测管道何时破裂的必要条件,例如当p2过早退出时。

如果没有p1.stdout.close(),那么p1.stdout在父进程中仍然是开放的,即使p2退出; p1不会知道没有人读取p1.stdout,即p1将继续写入p1.stdout,直到相应的OS管道缓冲区已满,然后它才会永久阻塞。

要在没有shell的情况下模拟foo | grep bar shell命令:

#!/usr/bin/env python3
from subprocess import Popen, PIPE

with Popen(['grep', 'bar'], stdin=PIPE) as grep, \
     Popen(['foo'], stdout=grep.stdin):
    grep.communicate()

How do I use subprocess.Popen to connect multiple processes by pipes?

以上是关于管道时在python的子进程模块中使用stdout.close()的主要内容,如果未能解决你的问题,请参考以下文章

当父进程为 64 位时,StdIN/StdOUT 管道出现问题

捕获stdout以获取远程进程的子进程

subprogress模块

python子进程模块subprocess详解与应用实例 之二

合并Python脚本的子进程'stdout和stderr,同时保持它们可区分

使用管道进行Python进程输入/输出