Python subprocess.Popen PIPE和SIGPIPE

时间:2017-12-28 05:04:12

标签: 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))

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

    SIGPIPE尝试写入已关闭的PIPE时,会发生
  1. PIPE
  2. 作家PIPEproc1 stdout而读者PIPEproc2&#39; s stdin。< / LI>
  3. proc1将在proc2退出时退出,proc1尝试将数据写入proc2 stdin PIPE。 因为
      {li> proc2&#39; stdin PIPEproc2退出时关闭
    • SIGPIPE发生在proc1,因为proc1试图写信至已关闭的proc2 stdin PIPE
  4. 根据我的理解,SIGPIPE会发生,proc1会退出,无论是否关闭proc1 stdout

    我想念什么?

    修改

    从@ 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错了,但我只想修复我的理解。提前谢谢。

1 个答案:

答案 0 :(得分:4)

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终止,因为它知道没有人正在监听其管道的另一端。