Python subprocess.Popen PIPE 和 SIGPIPE

San*_*Kim 4 python linux subprocess pipe sigpipe

当我浏览帖子时,我在这里遇到了下面的这个例子,它说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))
Run Code Online (Sandbox Code Playgroud)

但是,我并不清楚。请修正我的理解。

  1. SIGPIPE当 aPIPE尝试写入 closed时发生PIPE
  2. 作家PIPEproc1stdout和读者PIPEproc2stdin
  3. proc1退出时将退出proc2proc1尝试将数据写入proc2's stdin PIPE。因为
    • proc2stdin PIPE是,当关闭proc2退出
    • SIGPIPE发生在proc1因为proc1尝试写入关闭proc2stdin PIPE.

从我的理解,SIGPIPE总会发生,proc1将退出不管收,proc1stdout

我想念什么?


编辑

阅读@unutbu 评论中的帖子后......

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

因此,退出SIGPIPE时会生成,proc2因为proc2只有一个进程有读取器 PIPE(proc2退出时将关闭)。

但是,上面的帖子似乎是说通过复制有两个阅读器PIPE,proc1.stdout因此SIGPIPE即使proc2退出后也不会生成,因为还有另一个阅读器PIPE打开。以下是帖子的部分。

因此,通过立即关闭 p1.stdout,您可以确保从 dmesg stdout 读取的唯一剩余文件句柄是 grep 进程,如果该进程退出,dmesg 会收到一个 SIGPIPE。

我并不是说该帖子是错误的,但我只是想纠正我的理解。先感谢您。

unu*_*tbu 7

proc1 = subprocess.Popen(['ps', 'cax'], stdout=subprocess.PIPE)
Run Code Online (Sandbox Code Playgroud)

在父进程和proc1以下进程之间创建一个管道:

|        |         |       |
| parent |-<-----<-| proc1 |                   
|        | ^       |       |
           |                     
       p1.stdout   
Run Code Online (Sandbox Code Playgroud)

p1.stdout是父级从proc1.

proc2 = subprocess.Popen(['grep', 'python'], stdin=proc1.stdout,
                         stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Run Code Online (Sandbox Code Playgroud)

将管道的副本从 proc1 连接到 proc2:

|        |         |       |         |       |
| parent |-<-----<-| proc1 |->----->-| proc2 | 
|        |         |       |         |       |
Run Code Online (Sandbox Code Playgroud)

通过调用p1.stdout.close(),我们关闭了管道的父进程一侧:

|        |         |       |         |       |
| parent |       <-| proc1 |->----->-| proc2 | 
|        |         |       |         |       |
Run Code Online (Sandbox Code Playgroud)

现在,当proc2终止时,它的管道一侧也关闭了:

|        |         |       |         |       |
| parent |       <-| proc1 |->       | proc2 | 
|        |         |       |         |       |
Run Code Online (Sandbox Code Playgroud)

下一次proc1尝试写入管道时,会生成一个 SIGPIPE 信号,该信号允许proc1终止,因为它知道没有人在其管道的另一端监听。