在我浏览帖子的过程中,我在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
' s stdin
。< / LI>
proc1
将在proc2
退出时退出,proc1
尝试将数据写入proc2
stdin PIPE
。
因为
proc2
&#39; 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错了,但我只想修复我的理解。提前谢谢。
答案 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
终止,因为它知道没有人正在监听其管道的另一端。