当我浏览帖子时,我在下面的here上遇到了此示例,这就是说proc1的适当退出需要调用proc1.stdout.close(),从而生成SIGPIPE.
import subprocess
proc1 = subprocess.Popen(['ps', 'cax'], stdout=subprocess.PIPE)
proc2 = subprocess.Popen(['grep', 'python'], stdin=proc1.stdout,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
proc1.stdout.close() # Allow proc1 to receive a SIGPIPE if proc2 exits.
out, err = proc2.communicate()
print('out: {0}'.format(out))
print('err: {0}'.format(err))
但是,我不清楚.请修正我的理解.
>当PIPE尝试写入关闭的PIPE时,发生SIGPIPE.
>写入器PIPE是proc1的标准输出,而读取器PIPE是proc2的标准输入.
>当proc2退出并且proc1尝试将数据写入proc2的stdin PIPE时,proc1将退出.
因为
> proc2退出时proc2的stdin PIPE关闭
> SIGPIPE发生在proc1上,因为proc1试图写入已关闭的proc2的stdin PIPE.
据我了解,无论关闭proc1的stdout,SIGPIPE都会发生,而proc1将退出.
我想念什么?
编辑
从@unutbu的评论中阅读post后…
我认为复制的文件描述符(proc1.stdout)是写程序PIPE,而不是读程序PIPE.因此,有两个写入器PIPE和一个读取器PIPE相互连接.
因此,在proc2退出时将生成SIGPIPE,因为proc2只是一个具有读取器PIPE的进程(在proc2退出时将关闭).
但是,上面的post似乎表明通过复制proc1.stdout有两个读取器PIPE,因此即使proc2退出后也不会生成SIGPIPE,因为还有另一个读取器PIPE处于打开状态.以下是post的一部分.
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.
我并不是说post是错误的,但我只是想修正我的理解.先感谢您.
解决方法:
proc1 = subprocess.Popen(['ps', 'cax'], stdout=subprocess.PIPE)
在父进程和proc1之间创建一个管道:
| | | |
| parent |-<-----<-| proc1 |
| | ^ | |
|
p1.stdout
p1.stdout是父级将读取以从proc1获得(stdout)输出的内容.
proc2 = subprocess.Popen(['grep', 'python'], stdin=proc1.stdout,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
将管道的副本从proc1连接到proc2:
| | | | | |
| parent |-<-----<-| proc1 |->----->-| proc2 |
| | | | | |
通过调用p1.stdout.close(),我们关闭管道的父进程侧:
| | | | | |
| parent | <-| proc1 |->----->-| proc2 |
| | | | | |
现在,当proc2终止时,管道的一侧也将关闭:
| | | | | |
| parent | <-| proc1 |-> | proc2 |
| | | | | |
下次proc1尝试写入管道时,会生成SIGPIPE信号,
它允许proc1终止,因为它知道没人在其管道的另一端监听.