Python subprocess.Popen PIPE 和 SIGPIPE

Python subprocess.Popen PIPE and 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. SIGPIPEPIPE 尝试写入已关闭的 PIPE.
  2. 时发生
  3. 作家 PIPEproc1stdout,reader PIPEproc2stdin
  4. proc1 将在 proc2 退出并且 proc1 尝试将数据写入 proc2stdin PIPE 时退出。 因为
    • proc2stdin PIPEproc2退出时关闭
    • SIGPIPE 发生在 proc1 因为 proc1 试图写入已关闭的 proc2stdin PIPE.

根据我的理解,SIGPIPE 会发生并且 proc1 会退出,无论是否关闭 proc1stdout

我错过了什么?


编辑

阅读@unutbu 评论中的 后……

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

因此,proc2退出时会生成SIGPIPE,因为proc2只是一个有reader个PIPE的进程(会在proc2时关闭退出)。

但是上面的好像是说复制proc1.stdout有两个reader个PIPE所以SIGPIPE即使在[=23之后也不会生成=] 退出,因为还有另一个 reader PIPE 打开。下面是.

的部分

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.

我并不是说 是错误的,我只是想修正我的理解。提前谢谢你。

proc1 = subprocess.Popen(['ps', 'cax'], stdout=subprocess.PIPE)

在 parent 进程和 proc1 之间创建了一个管道:

|        |         |       |
| parent |-<-----<-| proc1 |                   
|        | ^       |       |
           |                     
       p1.stdout   

p1.stdout 是 parent 从 proc1.

获取(标准输出)输出的内容
proc2 = subprocess.Popen(['grep', 'python'], stdin=proc1.stdout,
                         stdout=subprocess.PIPE, stderr=subprocess.PIPE)

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

|        |         |       |         |       |
| parent |-<-----<-| proc1 |->----->-| proc2 | 
|        |         |       |         |       |

通过调用 p1.stdout.close(),我们关闭管道的 parent 进程端:

|        |         |       |         |       |
| parent |       <-| proc1 |->----->-| proc2 | 
|        |         |       |         |       |

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

|        |         |       |         |       |
| parent |       <-| proc1 |->       | proc2 | 
|        |         |       |         |       |

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