python—使用subprocess.popen通过管道连接多个进程时,如何避免死锁?

ghg1uchk  于 2021-08-20  发布在  Java
关注(0)|答案(1)|浏览(403)

这是@omry yadan在2018年12月9日关于subprocess.popen管道如何在python中工作的回答的后续问题?。我需要创建一个三个程序管道,并从所有三个程序中收集stderr和返回代码。基于2018年12月9日的答案,我目前的解决方案(如下)挂起。粘贴到shell中的等效命令很快完成。
从标准输出到标准输入的数据量为MB。最终的标准件以及三个标准件预计要小得多。


# !/usr/bin/env python3

cmd1 = ["gzip", "-dc", "some_file.gz"]
cmd2 = ["filtering_program", "some", "arguments"]
cmd3 = ["collection_program", "some", "arguments"]

p1 = Popen(cmd1, stdout=PIPE, stderr=PIPE)
p2 = Popen(cmd1, stdin=p1.stdout, stdout=PIPE, stderr=PIPE)]
p3 = Popen(cmd1, stdin=p2.stdout, stdout=PIPE, stderr=PIPE)]
(outcome_stdout, outcome_stderr) = p3.communicate()
p1.wait()
p2.wait()
4zcjmb1e

4zcjmb1e1#

注意记录的以下问题。还要注意的是,管道缓冲区增长到(macos),默认情况下限制为65536字节(现代linux)
波本,等等
注意,当使用stdout=pipe或stderr=pipe时,这将导致死锁,并且子进程将生成足够的输出到管道,从而阻止等待os管道缓冲区接受更多数据。使用管道时请使用popen.communicate()以避免这种情况。
popen.stderr
警告:请使用communicate()而不是.stdin.write、.stdout.read或.stderr.read,以避免由于任何其他操作系统管道缓冲区填满并阻塞子进程而导致死锁。

相关问题