什么时候应该使用subprocess.Popen而不是os.popen? [英] When should I use subprocess.Popen instead of os.popen?

查看:206
本文介绍了什么时候应该使用subprocess.Popen而不是os.popen?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

似乎都执行一个子过程并创建一个管道来执行输入/输出操作,只是subprocess是更新的.

我的问题是,subprocess.Popen可以执行什么功能,而os.popen不能执行什么功能,以便我们需要新的模块subprocess?

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

解决方案

简短答案:请勿使用os.popen,请始终使用 os.popen文档:

从2.6版开始不推荐使用:此功能已过时.使用 subprocess模块.尤其要检查替换旧功能 与子过程 模块部分.

旧的os.popen功能家族存在各种局限性和问题.而且,正如文档所述,2.6之前的版本在Windows上甚至都不可靠.

subprocess的动机在 PEP 324中进行了解释-子流程-新流程模块:

动机

在任何编程语言中,启动新流程都是一项常见的任务, 并且在像Python这样的高级语言中非常常见.良好的支持 之所以需要执行此任务,是因为:

  • 用于启动进程的不适当功能可能意味着 安全风险:如果程序是通过外壳启动的,并且 参数包含shell元字符,结果可以是 惨重. [1]

  • 它使Python成为了更好的替换语言 过于复杂的Shell脚本.

目前,Python具有许多不同的功能,可用于 流程创建.这使开发人员难以选择.

子流程模块在以下方面提供了以下增强功能: 以前的功能:

  • 一个统一"模块提供了以前版本的所有功能 功能.

  • 跨进程异常:子进程中发生异常 在重新开始执行新流程之前 父母.这意味着很容易处理exec() 例如失败.以popen2为例, 无法检测执行是否失败.

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

  • 没有隐式调用/bin/sh.这意味着没有必要 逃脱危险的外壳元字符.

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

  • 通过子流程模块,可以控制是否全部打开 在执行新程序之前,应关闭文件描述符 被执行.

  • 支持连接多个子进程(外壳管道").

  • 通用换行支持.

  • 一个communication()方法,可以轻松发送stdin数据 并读取stdout和stderr数据,而没有死锁的风险. 大多数人都知道与 子流程沟通,但并非所有人都有耐心或 编写完全正确且无死锁的选择循环的技巧. 这意味着许多Python应用程序都包含种族 情况.标准库中的communication()方法 解决了这个问题.

请查看PEP链接以了解基本原理以及更多详细信息.

除安全性和安全性外,可靠性问题,恕我直言,旧的os.popen系列既麻烦又令人困惑.在编码时,如果不仔细参考文档,几乎不可能正确使用.相比之下,subprocess是天赐之物,尽管在使用它时参考文档仍然是明智的. ;)

有时候,有人看到人们建议在Python 2.7中使用os.popen而不是subprocess.Popen,例如 os.popen本身在Python 3中仍然存在,但是可以通过subprocess.Popen安全地实现,因此您也可以直接直接使用subprocess.Popen. os.popen系列的其他成员在Python 3中不再存在.os.spawn函数系列在Python 3中仍然存在,但是文档建议改为使用subprocess模块提供的更强大的功能. /p>

Seems both executes a subprocess and create a pipe to do in/out, just that the subprocess is newer.

My question is, is there any function that subprocess.Popen can do while os.popen cannot, so that we need the new module subprocess?

Why Python language didn't choose to enhance os.popen but created a new module?

解决方案

Short answer: Never use os.popen, always use subprocess!

As you can see from the Python 2.7 os.popen docs:

Deprecated since version 2.6: This function is obsolete. Use the subprocess module. Check especially the Replacing Older Functions with the subprocess Module section.

There were various limitations and problems with the old os.popen family of functions. And as the docs mention, the pre 2.6 versions weren't even reliable on Windows.

The motivation behind subprocess is explained in PEP 324 -- subprocess - New process module:

Motivation

Starting new processes is a common task in any programming language, and very common in a high-level language like Python. Good support for this task is needed, because:

  • Inappropriate functions for starting processes could mean a security risk: If the program is started through the shell, and the arguments contain shell meta characters, the result can be disastrous. [1]

  • It makes Python an even better replacement language for over-complicated shell scripts.

Currently, Python has a large number of different functions for process creation. This makes it hard for developers to choose.

The subprocess module provides the following enhancements over previous functions:

  • One "unified" module provides all functionality from previous functions.

  • Cross-process exceptions: Exceptions happening in the child before the new process has started to execute are re-raised in the parent. This means that it's easy to handle exec() failures, for example. With popen2, for example, it's impossible to detect if the execution failed.

  • A hook for executing custom code between fork and exec. This can be used for, for example, changing uid.

  • No implicit call of /bin/sh. This means that there is no need for escaping dangerous shell meta characters.

  • All combinations of file descriptor redirection is possible. For example, the "python-dialog" [2] needs to spawn a process and redirect stderr, but not stdout. This is not possible with current functions, without using temporary files.

  • With the subprocess module, it's possible to control if all open file descriptors should be closed before the new program is executed.

  • Support for connecting several subprocesses (shell "pipe").

  • Universal newline support.

  • A communicate() method, which makes it easy to send stdin data and read stdout and stderr data, without risking deadlocks. Most people are aware of the flow control issues involved with child process communication, but not all have the patience or skills to write a fully correct and deadlock-free select loop. This means that many Python applications contain race conditions. A communicate() method in the standard library solves this problem.

Please see the PEP link for the Rationale, and further details.

Aside from the safety & reliability issues, IMHO, the old os.popen family was cumbersome and confusing. It was almost impossible to use correctly without closely referring to the docs while you were coding. In comparison, subprocess is a godsend, although it's still wise to refer to the docs while using it. ;)

Occasionally, one sees people recommending the use of os.popen rather than subprocess.Popen in Python 2.7, eg Python subprocess vs os.popen overhead because it's faster. Sure, it's faster, but that's because it doesn't do various things that are vital to guarantee that it's working safely!


FWIW, os.popen itself still exists in Python 3, however it's safely implemented via subprocess.Popen, so you might as well just use subprocess.Popen directly yourself. The other members of the os.popen family no longer exist in Python 3. The os.spawn family of functions still exist in Python 3, but the docs recommend that the more powerful facilities provided by the subprocess module be used instead.

这篇关于什么时候应该使用subprocess.Popen而不是os.popen?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆