subprocess模块具有便捷的功能call
,在2.6和3.1中都是这样实现的:
def call(*popenargs, **kwargs):
return Popen(*popenargs, **kwargs).wait()
该函数的文档带有红色警告,内容如下:
Warning: Like Popen.wait()
,这在使用时会死锁stdout=PIPE
and/or stderr=PIPE
并且子进程生成足够的输出到管道,以便它阻塞等待操作系统管道缓冲区接受更多数据。
The Popen.wait()
文档说要使用Popen.communicate()
相反,在这种情况下。那么为什么不呢call
只是像下面这样实现,所以可以删除愚蠢的警告,并从标准库中删除这样的愚蠢限制?
def call(*args, **kwargs):
input = kwargs.pop("input", None)
p = Popen(*args, **kwargs)
p.communicate(input)
return p.returncode
我确信这是有原因的。我缺少什么?
我花了一些时间浏览PEP-324 http://www.python.org/dev/peps/pep-0324/,其中引入了 subprocess 模块,试图弄清楚所涉及的设计决策,但我认为答案实际上非常简单:
There's 没有理由通过stdout=PIPE
or stderr=PIPE
to subprocess.call
,因此它可能会出现死锁这一事实是无关紧要的。
通过的唯一理由stdout=PIPE
or stderr=PIPE
to subprocess.Popen
以便您可以使用 Popen 实例的stdout
and stderr
作为文件对象的属性。自从subprocess.call
永远不会让您看到 Popen 实例,PIPE 选项变得无关紧要。
存在潜在的开销Popen.communicate
(通过监视管道创建额外的线程以避免死锁),在这种情况下没有任何好处,因此没有理由使用它。
Edit:如果你想放弃你的输出,我想最好明确地这样做:
# 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)
而不是指示子进程捕获您永远不打算使用的 PIPE 文件的所有输出。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)