Python subprocess.Popen PIPE和SIGPIPE

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python subprocess.Popen PIPE和SIGPIPE相关的知识,希望对你有一定的参考价值。

当我浏览帖子时,我在here上遇到了这个例子,它说proc1.stdout.close()需要被调用以适当退出proc1,生成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))

但是,我不清楚这一点。请理解我的理解。

  1. SIGPIPE发生在PIPE试图写入封闭的PIPE
  2. 作家PIPEproc1stdout和读者PIPEproc2stdin
  3. proc1退出时,proc2将退出,proc1试图将数据写入proc2stdin PIPE。因为 当proc2退出时,stdin PIPEproc2关闭 SIGPIPE发生在proc1因为proc1试图写封闭的proc2stdin PIPE

从我的理解,SIGPIPE将发生,proc1将退出,无论关闭proc1stdout

我错过了什么?


编辑

从@ unutbu的评论中读到post之后......

我认为复制的文件描述符(proc1.stdout)是编写者PIPE,而不是读者PIPE。因此,有两个作者PIPE和一个读者PIPE相互连接。

因此,当SIGPIPE退出时将生成proc2,因为proc2只有一个有读者PIPE的过程(当proc2退出时将关闭)。

然而,上面的post似乎说通过复制proc1.stdout有两个读者PIPE所以即使在SIGPIPE退出后也不会生成proc2,因为还有另一个读者PIPE打开。以下是post的一部分。

因此,通过立即关闭p1.stdout,您可以确保从dmesg stdout读取的唯一剩余文件句柄是grep进程,如果该进程要退出,则dmesg会收到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 subprocess.Popen PIPE和SIGPIPE的主要内容,如果未能解决你的问题,请参考以下文章

Python3 FileNotFoundError 与任何文件,使用 subprocess.popen()

subprocess.Popen不运行程序

使用 subprocess.Popen Python 执行两个命令 [重复]

subprocess.Popen 和缓冲的进程输出

将变量传递给 Subprocess.Popen

为什么Python命令“subprocess.Popen”找不到要运行的jar文件?