简体   繁体   English

Python subprocess.Popen PIPE和SIGPIPE

[英]Python subprocess.Popen PIPE and SIGPIPE

While I browsed posts, I ran into this example below on here , It is saying proc1.stdout.close() is needed to be called for appropriate exit of proc1 , generating 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))

However, I am not clear on that. 但是,我不清楚这一点。 Please fix my understanding. 请理解我的理解。

  1. SIGPIPE occurs when a PIPE tries to write to closed PIPE . PIPE尝试写入已关闭的PIPE时发生SIGPIPE
  2. Writer PIPE is proc1 's stdout and reader PIPE is proc2 's stdin . 作家PIPEproc1stdout ,读者PIPEproc2stdin
  3. proc1 will exit when proc2 exit and proc1 tries to write data to proc2 's stdin PIPE . proc1将在proc2退出时退出, proc1尝试将数据写入proc2stdin PIPE because 因为
    • proc2 's stdin PIPE is closed when proc2 exit proc2stdin PIPE被关闭时proc2退出
    • SIGPIPE happen at proc1 because proc1 tries to write to closed proc2 's stdin PIPE . SIGPIPE发生在proc1因为proc1试图写入已关闭的proc2stdin PIPE

From my understanding, SIGPIPE would happen and proc1 would exit, regardless of closing proc1 's stdout . 根据我的理解,无论关闭proc1stdoutSIGPIPE都会发生并且proc1会退出。

What do I miss? 我错过了什么?


Edit 编辑

After reading the post from @unutbu's comment...... 阅读@ unutbu评论后的帖子 ......

I think the copied file descriptor( proc1.stdout ) is writer PIPE, not reader PIPE. 我认为复制的文件描述符( proc1.stdout )是writer PIPE,而不是reader PIPE。 thus, there are two writer PIPE and one reader PIPE connected one another. 因此,有两个作者PIPE和一个读者PIPE相互连接。

Therefore, SIGPIPE will be generated when proc2 exit because proc2 is only one process which has reader PIPE(will be closed when proc2 exit). 因此,当proc2退出时将生成SIGPIPE因为proc2只是一个具有阅读器PIPE的进程(将在proc2退出时关闭)。

However, the above post seems to say that there are two reader PIPEs by copying proc1.stdout so SIGPIPE won't be generated even after proc2 exit because there still is another reader PIPE open. 但是,上面的帖子似乎说通过复制proc1.stdout有两个读者proc1.stdout所以即使在proc2退出后也不会生成SIGPIPE因为还有另一个读者PIPE打开。 the below is the part of 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. 因此,通过立即关闭p1.stdout,您可以确保从dmesg stdout读取的唯一剩余文件句柄是grep进程,如果该进程要退出,则dmesg会收到SIGPIPE。

I am not saying that the post is wrong but I just want to fix my understanding. 我并不是说帖子错了,但我只是想解决我的理解。 Thank you in advance. 先感谢您。

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

creates this a pipe between the parent process and proc1 : 在父进程和proc1之间创建一个管道:

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

p1.stdout is what the parent would read to obtain (stdout) output from proc1 . p1.stdout是父p1.stdoutproc1获取(stdout)输出的内容。

proc2 = subprocess.Popen(['grep', 'python'], stdin=proc1.stdout,
                         stdout=subprocess.PIPE, stderr=subprocess.PIPE)

connects a copy of the pipe from proc1 to proc2: 连接从proc1到proc2的管道副本:

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

By calling p1.stdout.close() , we close the parent processes's side of the pipe: 通过调用p1.stdout.close() ,我们关闭管道的父进程端:

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

Now when proc2 terminates, its side of the pipe is also closed: 现在,当proc2终止时,管道的一侧也会关闭:

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

The next time proc1 tries to write to the pipe, a SIGPIPE signal is generated, which allows proc1 to terminate since it knows no one is listening on the other end of its pipes. proc1下次尝试写入管道时,会生成一个SIGPIPE信号,该信号允许proc1终止,因为它知道没有人正在监听其管道的另一端。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM