关闭管道python子进程的stdout

时间:2011-09-12 17:36:04

标签: python shell subprocess pipeline

以下是我在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结束时会发生什么?

2 个答案:

答案 0 :(得分:14)

Wikipedia开始, SIGPIPE 是在尝试写入管道而没有连接到另一端的进程时发送给进程的信号。

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

使用p2创建stdin=p1.stdout时,现在有两个进程连接到管道p1.stdout

通常,当您在管道中运行进程时,您希望所有进程在任何进程结束时结束。要自动执行此操作,您需要关闭p1.stdout,因此p2.stdin是唯一附加到该管道的进程,如果p2结束且p1将其他数据写入stdout,它将收到一个SIGPIPE,因为该管道不再附加任何进程。

答案 1 :(得分:1)

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