Python subprocess.Popen PIPE 和 SIGPIPE

标签 python linux subprocess 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. SIGPIPEPIPE 时发生尝试写入已关闭的 PIPE .
  2. 作家 PIPEproc1stdout和阅读器PIPEproc2stdin .
  3. proc1将在 proc2 时退出退出和proc1尝试将数据写入 proc2stdin PIPE . 因为
    • proc2stdin PIPE proc2 时关闭退出
    • SIGPIPE发生在 proc1因为proc1尝试写入已关闭的 proc2stdin PIPE .

据我了解,SIGPIPE会发生并且proc1将退出,无论关闭 proc1stdout .

我错过了什么?


编辑

看完post来自@unutbu 的评论......

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

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

然而,以上post似乎是说通过复制 proc1.stdout 有两个读者 PIPE所以SIGPIPE即使在 proc2 之后也不会生成退出,因为还有另一个阅读器 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 subprocess.Popen PIPE 和 SIGPIPE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48001819/

相关文章:

python - 为什么我的使用 Queue 、 threading.Thread 和 subprocess 的多线程 python 脚本如此不稳定

python - 无法调用pyspark udf函数

python - 如何使树莓派之间的通信代码成为多线程?

linux - 从 "ps"获取完整结果

python - 当线程等待 stdout 时继续运行 python 脚本

Python Popen 输出到 C 程序,fget 在循环中读取相同的 stdin

python - 当 argparse 中未设置 optinal 时如何采用两个位置参数

python - 在 Jupyter 笔记本中使用 Matplotlib 进行交互式绘图时,图形未填充 Canvas

c - 在非标准位置构建 gcc-4.3.4 时遇到问题

linux - 使用脚本编号和复制具有奇数和偶数的文件