使用subprocess.Popen设置管道:为什么关闭stdout但不关闭stdin?

时间:2018-08-28 08:05:07

标签: python subprocess pipe

subprocess.popen1)的Python 3文档提供了以下管道示例代码:

from subprocess import Popen, PIPE
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]
  

启动p2之后调用p1.stdout.close()很重要,如果p2在p1之前退出,则p1才能接收SIGPIPE。

为什么这是必需的?先前的问题(Replacing Shell PipelineUnder what condition does a Python subprocess get a SIGPIPE?Explain example from python subprocess module)的答案表明p1.stdout具有多个阅读器,必须将其全部关闭以防止p1的输出管道从关闭。


p2.stdinp1.stdout之间是什么关系,我是否必须关闭p2.stdin

1 个答案:

答案 0 :(得分:0)

否,您不必关闭p2.stdin。实际上您不能,因为它没有。

这是因为stdin=p1.stdout,而Python流对象仅在stdin=subprocess.PIPE时创建。参见subprocess Popen.stdin docs


我编写了一个测试程序(Python 3),如果BrokenPipeError终止于CLOSE_P1 = True,但会永远旋转呢?如果CLOSE_P1 = False

from subprocess import Popen, PIPE


CLOSE_P1 = True


p1 = Popen("ffmpeg "
           "-f rawvideo -pixel_format rgb24 -video_size 1x1 -i - "
           "-c copy -f rawvideo -".split(), stdin=PIPE, stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
assert p2.stdin is None

if CLOSE_P1:
    p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
p2.terminate()
while 1:
    p1.stdin.write(b'fsdafhdsf9jd9s8ha0')