我什么时候应该使用 subprocess.Popen 而不是 os.popen?
When should I use subprocess.Popen instead of os.popen?
似乎既执行了一个子进程又创建了一个管道来做 in/out,只是 subprocess
更新了。
我的问题是,有没有什么功能是subprocess.Popen
可以做而os.popen
不能做的,所以我们需要新模块subprocess
?
为什么Python语言没有选择增强os.popen
而是创建了一个新模块?
简短回答:从不使用 os.popen
,始终使用 subprocess
!
从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.
旧的 os.popen
系列函数存在各种限制和问题。正如文档所提到的,2.6 之前的版本在 Windows.
上什至不可靠
subprocess
背后的动机在 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.
请参阅 PEP link 了解基本原理和更多详细信息。
除了安全性和可靠性问题,恕我直言,旧的 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
家族的其他成员不再存在于Python3中。os.spawn
家族的功能仍然存在于Python3中,但文档推荐更强大的设施由 subprocess
模块提供,改为使用。
似乎既执行了一个子进程又创建了一个管道来做 in/out,只是 subprocess
更新了。
我的问题是,有没有什么功能是subprocess.Popen
可以做而os.popen
不能做的,所以我们需要新模块subprocess
?
为什么Python语言没有选择增强os.popen
而是创建了一个新模块?
简短回答:从不使用 os.popen
,始终使用 subprocess
!
从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.
旧的 os.popen
系列函数存在各种限制和问题。正如文档所提到的,2.6 之前的版本在 Windows.
subprocess
背后的动机在 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.
请参阅 PEP link 了解基本原理和更多详细信息。
除了安全性和可靠性问题,恕我直言,旧的 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
家族的其他成员不再存在于Python3中。os.spawn
家族的功能仍然存在于Python3中,但文档推荐更强大的设施由 subprocess
模块提供,改为使用。