我什么时候应该使用subprocess.Popen而不是os.popen?

时间:2017-01-16 12:36:55

标签: python subprocess popen

似乎都执行一个子进程并创建一个输入/输出的管道,只是subprocess更新。

我的问题是,subprocess.Popen无法执行os.popen可以执行的任何功能,因此我们需要新模块subprocess吗?

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

1 个答案:

答案 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提供更强大的功能。而是使用模块。