Lau*_*low 13 python subprocess
子进程模块具有便捷功能call,在2.6和3.1中都是这样实现的:
def call(*popenargs, **kwargs):
return Popen(*popenargs, **kwargs).wait()
Run Code Online (Sandbox Code Playgroud)
该功能的文档带有红色警告,阅读:
警告:比如
Popen.wait(),当使用stdout=PIPE和/或stderr=PIPE子进程生成足够的输出到管道时它会死锁,这样它就会阻塞等待OS管道缓冲区接受更多数据.
该Popen.wait()文件说,使用Popen.communicate(),而不是在这种情况下.那么,为什么不call只是像下面那样实现,所以可以删除愚蠢的警告,并从标准库中删除这样的愚蠢限制?
def call(*args, **kwargs):
input = kwargs.pop("input", None)
p = Popen(*args, **kwargs)
p.communicate(input)
return p.returncode
Run Code Online (Sandbox Code Playgroud)
我确定这是有原因的.我错过了什么?
我花了一些时间浏览PEP-324,它介绍了子过程模块,试图找出所涉及的设计决策,但我认为答案实际上非常简单:
有没有理由来传递stdout=PIPE或stderr=PIPE到subprocess.call,这样一个事实,即它可以死锁是无关紧要的.
唯一的原因,传递stdout=PIPE或stderr=PIPE到subprocess.Popen是让你可以使用POPEN实例的stdout,并stderr为文件对象的属性.由于subprocess.call永远不会让您看到Popen实例,因此PIPE选项变得无关紧要.
Popen.communicate(通过监视管道来创建额外的线程以避免死锁)可能存在开销,并且在这种情况下没有任何好处,因此没有理由使用它.
编辑:如果你想丢弃你的输出,我想最好这样做明确:
# option 1
with open(os.devnull, 'w') as dev_null:
subprocess.call(['command'], stdout=dev_null, stderr=dev_null)
# option 2
subprocess.call(['command >& /dev/null'], shell=True)
Run Code Online (Sandbox Code Playgroud)
而不是指示子进程将所有输出捕获到您从未打算使用的PIPE文件.