2017-01-16 89 views
2

似乎都执行一个子进程,并创建一个管道进行/输出,只是子进程更新。Python:什么时候应该使用subprocess.Popen而不是os.popen?

我的问题是,subprocess.Popen可以做什么,而os.popen不能,所以我们需要一个新的子进程?

为什么python语言没有选择增强os.popen,但创建了一个新模块?

感谢

+4

从https://docs.python.org/2/library/os.html#os.popen“自2.6版弃用:此功能已过时,使用'subprocess'模块。” –

+2

请参阅https://www.python。org/dev/peps/pep-0324 /动机与理论部分:防范某些安全风险,跨进程异常,使用文件描述符更好的操作等。 –

+1

除了安全性和可靠性问题,恕我直言,老'os。波潘家族很麻烦,令人困惑。在编写代码时,如果没有密切提及文档,几乎不可能正确使用。相比之下,'subprocess'是天赐之物,尽管在使用文档时参考文档仍然是明智之举。 ;) –

回答

6

简短的回答:切勿使用os.popen,总是使用subprocess

你可以从Python 2.7 os.popen docs看到:

自2.6版本不推荐使用:此功能已经过时了。使用 subprocess模块。特别检查Replacing Older Functions with the subprocess Module部分。

旧功能家族存在各种限制和问题。正如文档中提到的那样,2.6之前的版本在Windows上甚至不可靠。

背后subprocess的动机是PEP 324 -- subprocess - New process module解释说:

动机

开始新的进程是任何编程语言, 一个共同的任务,并在像Python的高级语言很常见。良好的支持 需要这个任务,因为:

  • 启动过程可能意味着 安全风险不合适的功能:如果程序是通过shell启动,并 参数包含shell元字符,结果可能是 灾难性的。 [1]

  • 它使Python成为 过度复杂的shell脚本的更好替代语言。

目前,Python有 进程创建的大量不同的功能。这使开发人员很难选择。

的子模块提供了以下增强功能比以前 功能:

  • 一个“统一”模块提供了从以前的 功能的全部功能。

  • 跨进程异常:在新进程开始执行之前发生在子进程 中的异常在父进程 中重新提出。这意味着,例如,处理exec() 故障很容易。例如,对于popen2,如果执行失败,则无法检测到 。

  • 用于在fork和exec之间执行自定义代码的钩子。这个 可以用于,例如,改变uid。

  • 没有隐式调用/ bin/sh。这意味着不需要 来逃离危险的shell元字符。

  • 文件描述符重定向的所有组合都是可能的。例如,“python-dialog”[2]需要产生一个进程 并重定向stderr,但不是stdout。目前的功能无法使用临时文件,这是不可能的。

  • 随着子模块,它可以控制,如果之前的新方案是执行 所有打开的 文件描述符应该被关闭。

  • 支持连接多个子进程(shell“管道”)。

  • 通用换行支持。

  • 一个通信()方法,它可以很容易地发送标准输入数据 并读取标准输出和标准错误数据,而没有死锁风险。大多数人都知道 子进程通信中涉及的流量控制问题,但并非所有人都有耐心或 技能来编写完全正确且无死锁的选择循环。这意味着许多Python应用程序包含种族 条件。标准库 中的communications()方法解决了这个问题。

请参阅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直接自己。 os.popen系列的其他成员不再存在于Python 3中.功能家族仍然存在于Python 3中,但文档建议使用由subprocess模块提供的更强大的功能。

相关问题