当我浏览帖子时,我在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
试图写入封闭的PIPE
。PIPE
是proc1
的stdout
和读者PIPE
是proc2
的stdin
。proc1
退出时,proc2
将退出,proc1
试图将数据写入proc2
的stdin PIPE
。因为
当proc2
退出时,stdin PIPE
的proc2
关闭
SIGPIPE
发生在proc1
因为proc1
试图写封闭的proc2
的stdin PIPE
。从我的理解,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是错的,但我只是想解决我的理解。先感谢您。
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
终止,因为它知道没有人正在监听其管道的另一端。