问题 关闭管道python子进程的stdout


这是我在python子进程模块文档中可以读到的内容:

Replacing shell pipeline

    output=`dmesg | grep hda`
    ==>
    p1 = Popen(["dmesg"], stdout=PIPE)
    p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
    p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
    output = p2.communicate()[0]

The p1.stdout.close() call after starting the p2 is important in order for p1
to receive a SIGPIPE if p2 exits before p1.

我真的不明白为什么我们必须在创建p2之后关闭p1.stdout。 什么时候完全执行p1.stdout.close()? 当p2永远不会结束时会发生什么? 当p1或p2结束时会发生什么?


6696
2017-09-12 17:36


起源



答案:


维基百科SIGPIPE 是当进程尝试写入管道而没有连接到另一端的进程时发送到进程的信号。

当你第一次创建 p1 运用 stdout=PIPE,有一个进程连接到管道,这是您的Python进程,您可以使用读取输出 p1.stdout

当你创建 p2 运用 stdin=p1.stdout 现在有两个进程连接到管道 p1.stdout

通常,当您在管道中运行进程时,您希望所有进程在任何进程结束时结束。要自动发生这种情况,您需要关闭 p1.stdout 所以 p2.stdin 是唯一附加到该管道的进程,如果是这样的话 p2 结束和 p1 将附加数据写入stdout,它将收到一个SIGPIPE,因为不再有任何进程附加到该管道。


13
2017-09-12 17:46





好的我明白了。 p1.stdout从我的python脚本关闭但在p2中保持打开状态,然后p1和p2一起通信。 除非p2已经关闭,否则p1会收到一个SIGPIPE。 我对么?


1
2017-09-12 18:03



这是正确的,如果第一个流程的运行时间比第二个流程长很多,这一点很重要。 - Andrew Clark


答案:


维基百科SIGPIPE 是当进程尝试写入管道而没有连接到另一端的进程时发送到进程的信号。

当你第一次创建 p1 运用 stdout=PIPE,有一个进程连接到管道,这是您的Python进程,您可以使用读取输出 p1.stdout

当你创建 p2 运用 stdin=p1.stdout 现在有两个进程连接到管道 p1.stdout

通常,当您在管道中运行进程时,您希望所有进程在任何进程结束时结束。要自动发生这种情况,您需要关闭 p1.stdout 所以 p2.stdin 是唯一附加到该管道的进程,如果是这样的话 p2 结束和 p1 将附加数据写入stdout,它将收到一个SIGPIPE,因为不再有任何进程附加到该管道。


13
2017-09-12 17:46





好的我明白了。 p1.stdout从我的python脚本关闭但在p2中保持打开状态,然后p1和p2一起通信。 除非p2已经关闭,否则p1会收到一个SIGPIPE。 我对么?


1
2017-09-12 18:03



这是正确的,如果第一个流程的运行时间比第二个流程长很多,这一点很重要。 - Andrew Clark