似乎都执行一个子进程并创建一个输入/输出的管道,只是subprocess
更新。
我的问题是,subprocess.Popen
无法执行os.popen
可以执行的任何功能,因此我们需要新模块subprocess
吗?
为什么Python语言没有选择增强os.popen
但是创建了一个新模块?
答案 0 :(得分:6)
简答:永远不要使用os.popen
,始终使用subprocess
!
正如您在Python 2.7 os.popen
docs中看到的那样:
从2.6版开始不推荐使用:此功能已过时。使用
subprocess
模块。请特别检查Replacing Older Functions with the subprocess Module部分。
旧os.popen
系列函数存在各种限制和问题。正如文档所提到的,2.6之前的版本在Windows上甚至都不可靠。
PEP 324 -- subprocess - New process module中解释了subprocess
背后的动机:
<强>动机强>
启动新进程是任何编程语言的常见任务, 并且在Python等高级语言中非常常见。良好的支持 这项任务是必要的,因为:
启动流程的不当功能可能意味着a 安全风险:如果程序是通过shell启动的,那么 参数包含shell元字符,结果可以是 惨重。 [1]
它使Python成为更好的替代语言 过于复杂的shell脚本。
目前,Python拥有大量不同的功能 流程创建。这使得开发人员很难选择。
子进程模块提供以下增强功能 以前的功能:
一个“统一”模块提供以前的所有功能 功能
跨进程异常:孩子发生异常 在新进程开始执行之前重新引发 父母。这意味着它很容易处理exec() 例如,失败。以popen2为例,它就是 无法检测执行是否失败。
用于在fork和exec之间执行自定义代码的钩子。这个 例如,可用于更改uid。
没有/ bin / sh的隐式调用。这意味着没有必要 逃避危险的贝壳元字符。
可以进行文件描述符重定向的所有组合。 例如,“python-dialog”[2]需要生成一个进程 并重定向stderr,但不是stdout。这是不可能的 当前函数,不使用临时文件。
使用子进程模块,可以控制是否全部打开 文件描述符应该在新程序之前关闭 执行。
支持连接多个子进程(shell“pipe”)。
通用换行支持。
一个communic()方法,可以轻松发送stdin数据 并读取stdout和stderr数据,而不会有死锁的风险。 大多数人都知道涉及的流量控制问题 儿童过程沟通,但并非所有人都有耐心或 编写完全正确且无死锁的选择循环的技巧。 这意味着许多Python应用程序都包含种族 条件。标准库中的communic()方法 解决了这个问题。
请参阅PEP链接了解基本原理,以及更多详情。
除了安全和安全可靠性问题,恕我直言,旧的os.popen
家庭既麻烦又令人困惑。如果没有在编码时仔细引用文档,几乎不可能正确使用。相比之下,subprocess
是天赐之物,尽管在使用文档时引用文档仍然是明智之举。 ;)
偶尔会有人看到人们建议在Python 2.7中使用os.popen
而不是subprocess.Popen
,例如Python subprocess vs os.popen overhead,因为它更快。当然,它更快,但这是因为它没有做各种事情,这些事情对于保证它安全运行至关重要!
FWIW,os.popen
itself still exists in Python 3,但它可以通过subprocess.Popen
安全地实施,因此您也可以直接自己使用subprocess.Popen
。 Python 3中不再存在os.popen
系列的其他成员。{3}中的os.spawn
系列函数仍然存在,但文档建议subprocess
提供更强大的功能。而是使用模块。