python替换shell管道

时间:2018-06-12 12:08:48

标签: python subprocess pipe

关于示例found here

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]

如何将其扩展为3流程管道?

另外,我找不到,p1.stdout.close()到底是做什么的?如果p1运行很长时间怎么办?在应用close()之前它会等待p1完成吗?

必须在沟通()之前关闭()?

我是否正确理解在调用communication()之前,管道已设置,但“保持”?或者更确切地说,每个进程都是立即并行启动的,但是需要从stdin输入的进程才会阻塞,直到调用了communic()?

考虑:

output=`dmesg | grep hda | grep bla`

也许是这样的:

p1 = Popen(["dmesg"], stdout=PIPE)
p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.

p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p2.stdout.close()  # Allow p2 to receive a SIGPIPE if p3 exits.

p3 = Popen(["grep", "bla"], stdin=p2.stdout, stdout=PIPE)

output = p3.communicate()[0]

(上面的那个以当前形式与ValueError: I/O operation on closed file崩溃)

这个不会抛出错误,但由于我不理解close(),它可能会在以后的某个时间设置为doom:

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.

p3 = Popen(["grep", "bla"], stdin=p2.stdout, stdout=PIPE)

p2.stdout.close()  # Allow p2 to receive a SIGPIPE if p3 exits.

output = p3.communicate()[0]

或者这个:

p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p3 = Popen(["grep", "bla"], stdin=p2.stdout, stdout=PIPE)

p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
p2.stdout.close()  # Allow p2 to receive a SIGPIPE if p3 exits.

output = p3.communicate()[0]

1 个答案:

答案 0 :(得分:0)

根据https://docs.python.org/2/library/subprocess.html的python文档项17.1.4.2,在启动p2之后调用p1.stdout.close()非常重要,以便p1在p1之前退出时接收SIGPIPE。 同样,也应在启动p3后调用p2.stdout.close()。

How to handle a broken pipe (SIGPIPE) in python?解释了如何处理损坏的管道(SIGPIPE)。