subprocess.call()和subprocess.Popen()之间的区别是什么使PIPE对前者不太安全?

Nat*_*ese 15 python subprocess popen python-2.6 python-2.7

我已经看过他们两个的文档了.

这个问题是由JF在这里的评论提示的:检索subprocess.call()的输出

当前的Python文档subprocess.call()说明了以下关于使用PIPE的内容subprocess.call():

注意请勿使用stdout=PIPEstderr=PIPE使用此功能.子进程将阻塞它是否为管道生成足够的输出以填充OS管道缓冲区,因为没有读取管道.

Python 2.7 subprocess.call():

注意请勿使用stdout=PIPEstderr=PIPE使用此功能,因为它可能会基于子进程输出量死锁.需要管道时,使用Popen和communic()方法.

Python 2.6不包含此类警告.

此外,subprocess.call()subprocess.check_call()似乎并不有一种方法来访问他们的输出,除了使用标准输出=管与沟通():

https://docs.python.org/2.6/library/subprocess.html#convenience-functions

请注意,如果要将数据发送到进程stdin,则需要使用创建Popen对象stdin=PIPE.同样,要在结果元组中获取除None之外的任何内容,您需要给出stdout=PIPE和/或stderr=PIPE过.

https://docs.python.org/2.6/library/subprocess.html#subprocess.Popen.communicate

之间有什么区别subprocess.call(),并subprocess.Popen()PIPE不够安全subprocess.call()

更具体:为什么subprocess.call() "基于子进程输出量的死锁".,不是Popen()吗?

jfs*_*jfs 19

call()只是Popen().wait()(±错误处理).

您不应该使用stdout=PIPEwith,call()因为它不会从管道中读取,因此子进程将在填充相应的OS管道缓冲区后立即挂起.这是一张图片,显示了数据如何在command1 | command2shell管道中流动:

管道/ stdio缓冲区

你的Python版本是什么并不重要 - 管道缓冲区(看图片)不在你的Python进程之内.Python 3不使用C stdio,但它只影响内部缓冲.刷新内部缓冲区后,数据将进入管道.如果command2(您的父Python程序)没有从管道中读取,那么command1(子进程,例如,启动call())将在管道缓冲区已满时挂起(pipe_size = fcntl(p.stdout, F_GETPIPE_SZ)在我的Linux机器上为~65K(最大值为/proc/sys/fs/pipe-max-size~1M)).

stdout=PIPE如果您稍后从管道读取,例如,使用Popen.communicate()方法,您可以使用.您也可以直接读取process.stdout(代表管道的文件对象).