【问题标题】:closing stdout of piped python subprocess关闭管道 python 子进程的标准输出
【发布时间】:2023-05-14 05:17:02
【问题描述】:

这是我在 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 永远不会结束时会发生什么? 当 nor p1 或 p2 结束时会发生什么?

【问题讨论】:

    标签: python shell subprocess pipeline


    【解决方案1】:

    来自WikipediaSIGPIPE 是当进程尝试写入管道而没有进程连接到另一端时发送给进程的信号。

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

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

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 没错,如果第一个进程比第二个进程运行的时间更长,这一点很重要。
      最近更新 更多