Python 更换壳体管道
在子流程模块的Python 2.7文档中,我发现了以下代码片段:Python 更换壳体管道,python,python-2.7,Python,Python 2.7,在子流程模块的Python 2.7文档中,我发现了以下代码片段: p1 = Popen(["dmesg"], stdout=PIPE) p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits. output = p2.communicate()[0] 资料来源: 我不明白这行:p1.stdout.close()
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits.
output = p2.communicate()[0]
资料来源:
我不明白这行:p1.stdout.close()#如果p2退出,允许p1接收SIGPIPE。
这里p1.stdout正在关闭。如果p2退出,它如何允许p1接收SIGPIPE?如果进程试图写入没有活动进程正在查看的管道,通常会发送SIGPIPE信号。在与代码段等效的shell管道中:
`dmesg | grep hda`
如果grep
进程由于某种原因在dmesg
完成写入输出之前终止,dmesg
将收到一个SIGPIPE并自行终止。这将是UNIX/Linux进程()的预期行为
相反,在使用subprocess
的Python实现中,如果p2
在p1
生成输出之前退出,SIGPIPE不会被发送,因为实际上仍然有一个进程在查看管道——Python脚本本身(创建p1
和p2
)。更重要的是,脚本正在查看管道,但不使用其内容-其效果是管道无限期地保持打开状态,p1
陷入了困境
显式关闭p1.stdout
将Python脚本从管道中分离出来,并使其成为除p2
以外的任何进程都不会查看管道-这样,如果p2
确实在p1
之前结束,p1
正确地获得结束自身的信号,而无需任何人为地保持管道打开
以下是另一种措辞的解释:
来自:
当进程试图写入未连接到另一端的进程的管道时,SIGPIPE信号被发送到进程。使用stdin=p1.stdout
创建p2时,有两个进程连接到管道p1.stdout
:父python进程和p2。即使p2提前关闭,父进程仍在运行,因此不会发送SIGPIPE信号p1.stdout.close()
关闭父/调用方进程中的p1.stdout
,从而使dmesg成为打开该文件描述符的唯一进程
换句话说,如果没有p1.stdout.close()
在父进程中保持打开状态。如果p2退出(即存在 没有人读p1.stdout),p1不会知道没有人读p1.stdout
并将继续写入p1.stdout
,直到 相应的操作系统管道缓冲区已满p1.stdout
- 如果p2过早退出,
仍将是 在父进程中打开,因此不会生成SIGPIPEp1.stdout
- 管道是由操作系统管理的实例。它有一个读端和一个写端
- 两端可以由多个进程打开。不过,仍然只有一根管子。也就是说,多个进程可以共享同一个管道
- 打开其中一端的进程拥有相应的文件句柄。进程可以主动
再次关闭它!如果进程退出,操作系统将为您关闭相应的文件句柄close()
- 所有涉及的进程都可以
它们代表管道读取端的文件句柄。这没什么错,这是一个完美的局面close()
- 现在,如果进程将数据写入管道的写入端,而读取端不再打开(没有进程持有读取端的打开文件句柄),符合POSIX的操作系统会向写入进程发送一个
信号,让它知道不再有读卡器SIGPIPE
- 一个更系统的解释:
cat bigfile | head -n5
实际上读取整个大文件?不,它没有,因为cat
在head
退出时(从stdin读取5行后)立即检索SIGPIPE
信号。需要注意的一点是:cat
被设计为实际响应SIGPIPE
(这是一个重要的工程决策;):它停止读取文件并退出。其他程序被设计为忽略SIGPIPE(有意地,它们自己处理这种情况——这在网络应用程序中很常见)
如果在控制过程中保持管道的读取端打开,则禁用所述机制dmesg
将无法注意到grep
已退出
然而,你的例子实际上不是一个好例子<代码>grep hda将读取整个输入
dmesg
是首先退出的进程。“没有活动进程正在查看的管道”和“仍然是正在查看管道的流程”并不是真正精确的措辞。
cat bigfile | head -n5