Python子进程.Popen PIPE和SIGPIPE

当我浏览帖子时,我在下面的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终止,因为它知道没人在其管道的另一端监听.

上一篇:Python-无法调用系统命令


下一篇:Python开放追加无法正常工作