似乎两者都可以执行子进程并创建管道进行输入/输出,只是 subprocess
是较新的。
我的问题是,是否有任何 subprocess.Popen
可以做到而 os.popen
不能做到的功能,因此我们需要新模块 subprocess
?
为什么 Python 语言没有选择增强 os.popen
而是创建了一个新模块?
似乎两者都可以执行子进程并创建管道进行输入/输出,只是 subprocess
是较新的。
我的问题是,是否有任何 subprocess.Popen
可以做到而 os.popen
不能做到的功能,因此我们需要新模块 subprocess
?
为什么 Python 语言没有选择增强 os.popen
而是创建了一个新模块?
os.popen
,始终使用subprocess
!os.popen
docs可以看出:subprocess
模块。特别检查替换旧功能为子进程模块部分。os.popen
函数族存在各种限制和问题。正如文档所述,早期版本甚至在Windows上都不可靠。
subprocess
背后的动机在PEP 324 -- subprocess - New process module中解释。
请查看PEP链接以获取理由和更多细节。动机
在任何编程语言中,启动新进程都是常见任务,尤其在高级语言如Python中更为常见。需要良好的支持来完成此任务,因为:
不适当的启动进程函数可能会带来安全风险:如果程序通过shell启动,并且参数包含shell元字符,则结果可能会灾难性。[1]
它使Python成为替代过于复杂的shell脚本的更好语言。
目前,Python有大量不同的用于进程创建的函数。这使得开发人员很难做出选择。
subprocess模块提供了以下功能优化:
一个“统一”的模块提供了所有以前函数的功能。
跨进程异常:在新进程开始执行之前发生在子进程中的异常将在父进程中重新引发。这意味着很容易处理exec()失败。例如,使用popen2是无法检测到执行是否失败的。
在fork和exec之间执行自定义代码的钩子。例如,可以用于更改uid。
没有/bin/sh的隐式调用。这意味着不需要转义危险的shell元字符。
可以使用所有文件描述符重定向的组合。例如,“python-dialog” [2]需要生成一个进程并重定向stderr,但不重定向stdout。这在当前函数中是不可能的,除非使用临时文件。
使用subprocess模块,可以控制在执行新程序之前是否应关闭所有打开的文件描述符。
支持连接多个子进程(shell“pipe”)。
通用换行符支持。
communicate()方法使发送stdin数据和读取stdout和stderr数据变得容易,而不会出现死锁风险。大多数人都知道与子进程通信涉及的流量控制问题,但并非所有人都有耐心或技能编写完全正确且无死锁的select循环。标准库中的communicate()方法解决了这个问题。
顺便提一下,os.popen
在Python 3中仍然存在, 但是它是通过subprocess.Popen
安全实现的,因此你可以直接使用subprocess.Popen
。 os.popen
家族的其他成员在Python 3中已不存在。 os.spawn
函数族在Python 3中仍然存在,但文档建议使用subprocess
模块提供的更强大的功能。