【发布时间】:2018-09-18 01:39:00
【问题描述】:
我在subprocess documentation 中找到了这段代码,其中一个进程的标准输出正在通过管道传输到另一个进程:
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]
我对那个stdout.close() 电话感到困惑。确定关闭标准输出句柄会阻止进程产生任何输出吗?
所以我进行了一个实验,令我惊讶的是,这个过程根本没有受到影响:
from subprocess import Popen, PIPE
p1 = Popen(['python', '-c', 'import time; time.sleep(5); print(1)'], stdout=PIPE)
p2 = Popen(['python', '-c', 'print(input()*3)'], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits.
print('stdout closed')
print('stdout:', p2.communicate()[0])
# output:
# stdout closed
# [5 second pause]
# stdout: b'111\n'
这里发生了什么?为什么进程可以写入封闭管道?
【问题讨论】:
-
p1.stdout是 Python 对象 连接 到dmesg的标准输出;它不是dmesg实际使用的文件描述符。同样,grep的标准输入在您尝试关闭它之前已经获得了自己的文件句柄副本。 -
@chepner 我想这是有道理的,但是如果我们关闭输出管道又有什么关系呢?如果这只是一个副本,为什么关闭它会允许进程接收 SIGPIPE?
-
它没有;如果
dmesg在grep关闭后尝试写入其管道末端,则它会获得一个 SIGPIPE。在正常操作下,dmesg写入它需要的内容,然后正常退出。另一方面,grep保持打开状态,直到它看到它正在 读取 的管道已关闭,然后正常退出。除非grep提前终止,并且在dmesg完成写入输出之前,否则不会发送SIGPIPE。 -
简而言之,管道、进程和信号令人困惑。明白了。有一半没看懂,不过还是很感谢你的解释,谢谢。我想我有一些关于维基百科的阅读要做。
-
我没有发布答案的原因是我几乎可以肯定这其中有一些微妙的方面我没有正确解释。 :)
标签: python subprocess pipe