问题描述
我正在子进程模块部分中阅读有关Popen类的Python文档,并且遇到了以下代码:
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]
文档还指出
为什么在我们收到SIGPIPE之前必须先关闭p1.stdout,如果已经关闭p1,p1如何知道p2在p1之前退出?
SIGPIPE
是一个信号,如果dmesg
尝试写入封闭的管道,该信号将被发送.在这里,dmesg
最终以两个目标写入,即您的Python进程和grep
进程.
这是因为subprocess
克隆文件句柄(使用 os.dup2()
功能).将p2
配置为使用p1.stdout
会触发一个os.dup2()
调用,该调用要求操作系统复制管道文件句柄.副本用于将dmesg
连接到grep
.
具有两个用于dmesg
stdout的打开文件句柄,如果只有一个提前关闭,则不会向dmesg
发出SIGPIPE
信号,因此将永远不会检测到grep
关闭. dmesg
会不必要地继续产生输出.
因此,通过立即关闭p1.stdout
,可以确保从dmesg
stdout读取的唯一剩余文件句柄是grep
进程,并且如果该进程要退出,则dmesg
会收到SIGPIPE
. >
I am reading the the Python documentation on the Popen class in the subprocess module section and I came across the following code:
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 documentation also states that
Why must the p1.stdout be closed before we can receive a SIGPIPE and how does p1 knows that p2 exits before p1 if we already closed it?
SIGPIPE
is a signal that would be sent if dmesg
tried to write to a closed pipe. Here, dmesg
ends up with two targets to write to, your Python process and the grep
process.
That's because subprocess
clones file handles (using the os.dup2()
function). Configuring p2
to use p1.stdout
triggers a os.dup2()
call that asks the OS to duplicate the pipe filehandle; the duplicate is used to connect dmesg
to grep
.
With two open file handles for dmesg
stdout, dmesg
is never given a SIGPIPE
signal if only one of them closes early, so grep
closing would never be detected. dmesg
would needlessly continue to produce output.
So by closing p1.stdout
immediately, you ensure that the only remaining filehandle reading from dmesg
stdout is the grep
process, and if that process were to exit, dmesg
receives a SIGPIPE
.
这篇关于在什么情况下,Python子进程会获得SIGPIPE?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!