Python subprocess.Popen PIPE 和 SIGPIPE
Python subprocess.Popen PIPE and 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
尝试写入已关闭的 PIPE
. 时发生
- 作家
PIPE
是 proc1
的 stdout
,reader PIPE
是 proc2
的 stdin
。
proc1
将在 proc2
退出并且 proc1
尝试将数据写入 proc2
的 stdin PIPE
时退出。
因为
proc2
的stdin PIPE
在proc2
退出时关闭
SIGPIPE
发生在 proc1
因为 proc1
试图写入已关闭的 proc2
的 stdin PIPE
.
根据我的理解,SIGPIPE
会发生并且 proc1
会退出,无论是否关闭 proc1
的 stdout
。
我错过了什么?
编辑
阅读@unutbu 评论中的 后……
我认为复制的文件描述符(proc1.stdout
) 是writer PIPE,而不是reader PIPE。因此,有两个 writer PIPE 和一个 reader PIPE 相互连接。
因此,proc2
退出时会生成SIGPIPE
,因为proc2
只是一个有reader个PIPE的进程(会在proc2
时关闭退出)。
但是上面的好像是说复制proc1.stdout
有两个reader个PIPE所以SIGPIPE
即使在[=23之后也不会生成=] 退出,因为还有另一个 reader PIPE 打开。下面是.
的部分
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.
我并不是说 是错误的,我只是想修正我的理解。提前谢谢你。
proc1 = subprocess.Popen(['ps', 'cax'], stdout=subprocess.PIPE)
在 parent 进程和 proc1
之间创建了一个管道:
| | | |
| parent |-<-----<-| proc1 |
| | ^ | |
|
p1.stdout
p1.stdout
是 parent 从 proc1
.
获取(标准输出)输出的内容
proc2 = subprocess.Popen(['grep', 'python'], stdin=proc1.stdout,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
将管道的副本从 proc1 连接到 proc2:
| | | | | |
| parent |-<-----<-| proc1 |->----->-| proc2 |
| | | | | |
通过调用 p1.stdout.close()
,我们关闭管道的 parent 进程端:
| | | | | |
| parent | <-| proc1 |->----->-| proc2 |
| | | | | |
现在当 proc2
终止时,管道的一侧也关闭了:
| | | | | |
| parent | <-| proc1 |-> | proc2 |
| | | | | |
下次 proc1
尝试写入管道时,会生成 SIGPIPE 信号,
这允许 proc1
终止,因为它知道没有人在其管道的另一端监听。
当我浏览帖子时,我在 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
,readerPIPE
是proc2
的stdin
。 proc1
将在proc2
退出并且proc1
尝试将数据写入proc2
的stdin PIPE
时退出。 因为proc2
的stdin PIPE
在proc2
退出时关闭SIGPIPE
发生在proc1
因为proc1
试图写入已关闭的proc2
的stdin PIPE
.
根据我的理解,SIGPIPE
会发生并且 proc1
会退出,无论是否关闭 proc1
的 stdout
。
我错过了什么?
编辑
阅读@unutbu 评论中的
我认为复制的文件描述符(proc1.stdout
) 是writer PIPE,而不是reader PIPE。因此,有两个 writer PIPE 和一个 reader PIPE 相互连接。
因此,proc2
退出时会生成SIGPIPE
,因为proc2
只是一个有reader个PIPE的进程(会在proc2
时关闭退出)。
但是上面的proc1.stdout
有两个reader个PIPE所以SIGPIPE
即使在[=23之后也不会生成=] 退出,因为还有另一个 reader PIPE 打开。下面是
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.
我并不是说
proc1 = subprocess.Popen(['ps', 'cax'], stdout=subprocess.PIPE)
在 parent 进程和 proc1
之间创建了一个管道:
| | | |
| parent |-<-----<-| proc1 |
| | ^ | |
|
p1.stdout
p1.stdout
是 parent 从 proc1
.
proc2 = subprocess.Popen(['grep', 'python'], stdin=proc1.stdout,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
将管道的副本从 proc1 连接到 proc2:
| | | | | |
| parent |-<-----<-| proc1 |->----->-| proc2 |
| | | | | |
通过调用 p1.stdout.close()
,我们关闭管道的 parent 进程端:
| | | | | |
| parent | <-| proc1 |->----->-| proc2 |
| | | | | |
现在当 proc2
终止时,管道的一侧也关闭了:
| | | | | |
| parent | <-| proc1 |-> | proc2 |
| | | | | |
下次 proc1
尝试写入管道时,会生成 SIGPIPE 信号,
这允许 proc1
终止,因为它知道没有人在其管道的另一端监听。