[Python-checkins] cpython (2.7): Issue #13237: further updates to subprocess documentation
nick.coghlan
python-checkins at python.org
Wed Oct 26 13:06:17 CEST 2011
http://hg.python.org/cpython/rev/0b4df6701c4d
changeset: 73131:0b4df6701c4d
branch: 2.7
parent: 73125:a7191ec811c6
user: Nick Coghlan <ncoghlan at gmail.com>
date: Wed Oct 26 21:05:56 2011 +1000
summary:
Issue #13237: further updates to subprocess documentation
files:
Doc/library/subprocess.rst | 154 +++++++++++++++---------
1 files changed, 97 insertions(+), 57 deletions(-)
diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst
--- a/Doc/library/subprocess.rst
+++ b/Doc/library/subprocess.rst
@@ -31,12 +31,12 @@
Using the subprocess Module
---------------------------
-The recommended interface to this module is to use the following convenience
-functions for all use cases they can handle. For more advanced use cases, the
-underlying :class:`Popen` interface can be used directly.
+The recommended approach to invoking subprocesses is to use the following
+convenience functions for all use cases they can handle. For more advanced
+use cases, the underlying :class:`Popen` interface can be used directly.
-.. function:: call(args, *, stdin=None, stdout=None, stderr=None)
+.. function:: call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
Run the command described by *args*. Wait for command to complete, then
return the :attr:`returncode` attribute.
@@ -51,15 +51,15 @@
>>> subprocess.call(["ls", "-l"])
0
- >>> subprocess.call(["python", "-c", "import sys; sys.exit(1)"])
+ >>> subprocess.call("exit 1", shell=True)
1
.. warning::
- Like :meth:`Popen.wait`, this will deadlock when using
- ``stdout=PIPE`` and/or ``stderr=PIPE`` and the child process
- generates enough output to a pipe such that it blocks waiting
- for the OS pipe buffer to accept more data.
+ Do not use ``stdout=PIPE`` or ``stderr=PIPE`` with this function. As
+ the pipes are not being read in the current process, the child
+ process may block if it generates enough output to a pipe to fill up
+ the OS pipe buffer.
.. function:: check_call(*callargs, **kwargs)
@@ -74,10 +74,10 @@
>>> subprocess.check_call(["ls", "-l"])
0
- >>> subprocess.check_call(["python", "-c", "import sys; sys.exit(1)"])
+ >>> subprocess.check_call("exit 1", shell=True)
Traceback (most recent call last):
...
- subprocess.CalledProcessError: Command '['python', '-c', 'import sys; sys.exit(1)']' returned non-zero exit status 1
+ subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1
.. versionadded:: 2.5
@@ -95,27 +95,46 @@
:attr:`returncode` attribute and any output in the :attr:`output`
attribute.
+ The arguments are the same as for :func:`call`, except that *stdout* is
+ not permitted as it is used internally.
+
Examples::
- >>> subprocess.check_output(["ls", "-l", "/dev/null"])
- 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n'
+ >>> subprocess.check_output(["echo", "Hello World!"])
+ b'Hello World!\n'
- >>> subprocess.check_output(["python", "-c", "import sys; sys.exit(1)"])
+ >>> subprocess.check_output(["echo", "Hello World!"], universal_newlines=True)
+ 'Hello World!\n'
+
+ >>> subprocess.check_output("exit 1", shell=True)
Traceback (most recent call last):
...
- subprocess.CalledProcessError: Command '['python', '-c', 'import sys; sys.exit(1)']' returned non-zero exit status 1
+ subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1
- The arguments are the same as for :func:`call`, except that *stdout* is
- not allowed as it is used internally. To also capture standard error in
- the result, use ``stderr=subprocess.STDOUT``::
+ By default, this function will return the data as encoded bytes. The actual
+ encoding of the output data may depend on the command being invoked, so the
+ decoding to text will often need to be handled at the application level.
+
+ This behaviour may be overridden by setting *universal_newlines* to
+ :const:`True` as described below in :ref:`frequently-used-arguments`.
+
+ To also capture standard error in the result, use
+ ``stderr=subprocess.STDOUT``::
>>> subprocess.check_output(
- ... ["/bin/sh", "-c", "ls non_existent_file; exit 0"],
- ... stderr=subprocess.STDOUT)
+ ... "ls non_existent_file; exit 0",
+ ... stderr=subprocess.STDOUT,
+ ... shell=True)
'ls: non_existent_file: No such file or directory\n'
.. versionadded:: 2.7
+ .. warning::
+
+ Do not use ``stderr=PIPE`` with this function. As the pipe is not being
+ read in the current process, the child process may block if it
+ generates enough output to the pipe to fill up the OS pipe buffer.
+
.. data:: PIPE
@@ -141,10 +160,13 @@
most typical use cases, many of these arguments can be safely left at their
default values. The arguments that are most commonly needed are:
- *args* should be a string, or a sequence of program arguments. Providing
- a sequence of arguments is generally preferred, as it allows the module to
- take care of any required escaping and quoting of arguments (e.g. to permit
- spaces in file names)
+ *args* is required for all calls and should be a string, or a sequence of
+ program arguments. Providing a sequence of arguments is generally
+ preferred, as it allows the module to take care of any required escaping
+ and quoting of arguments (e.g. to permit spaces in file names). If passing
+ a single string, either *shell* must be :const:`True` (see below) or else
+ the string must simply name the program to be executed without specifying
+ any arguments.
*stdin*, *stdout* and *stderr* specify the executed program's standard input,
standard output and standard error file handles, respectively. Valid values
@@ -156,6 +178,37 @@
the stderr data from the child process should be captured into the same file
handle as for stdout.
+ When *stdout* or *stderr* are pipes and *universal_newlines* is
+ :const:`True` then the output data is assumed to be encoded as UTF-8 and
+ will automatically be decoded to text. All line endings will be converted
+ to ``'\n'`` as described for the universal newlines `'U'`` mode argument
+ to :func:`open`.
+
+ If *shell* is :const:`True`, the specified command will be executed through
+ the shell. This can be useful if you are using Python primarily for the
+ enhanced control flow it offers over most system shells and still want
+ access to other shell features such as filename wildcards, shell pipes and
+ environment variable expansion.
+
+ .. warning::
+
+ Executing shell commands that incorporate unsanitized input from an
+ untrusted source makes a program vulnerable to `shell injection
+ <http://en.wikipedia.org/wiki/Shell_injection#Shell_injection>`_,
+ a serious security flaw which can result in arbitrary command execution.
+ For this reason, the use of *shell=True* is **strongly discouraged** in cases
+ where the command string is constructed from external input::
+
+ >>> from subprocess import call
+ >>> filename = input("What file would you like to display?\n")
+ What file would you like to display?
+ non_existent; rm -rf / #
+ >>> call("cat " + filename, shell=True) # Uh-oh. This will end badly...
+
+ ``shell=False`` disables all shell based features, but does not suffer
+ from this vulnerability; see the Note in the :class:`Popen` constructor
+ documentation for helpful hints in getting ``shell=False`` to work.
+
These options, along with all of the other options, are described in more
detail in the :class:`Popen` constructor documentation.
@@ -216,24 +269,6 @@
Popen(['/bin/sh', '-c', args[0], args[1], ...])
- .. warning::
-
- Executing shell commands that incorporate unsanitized input from an
- untrusted source makes a program vulnerable to `shell injection
- <http://en.wikipedia.org/wiki/Shell_injection#Shell_injection>`_,
- a serious security flaw which can result in arbitrary command execution.
- For this reason, the use of *shell=True* is **strongly discouraged** in cases
- where the command string is constructed from external input::
-
- >>> from subprocess import call
- >>> filename = input("What file would you like to display?\n")
- What file would you like to display?
- non_existent; rm -rf / #
- >>> call("cat " + filename, shell=True) # Uh-oh. This will end badly...
-
- *shell=False* does not suffer from this vulnerability; the above Note may be
- helpful in getting code using *shell=False* to work.
-
On Windows: the :class:`Popen` class uses CreateProcess() to execute the child
child program, which operates on strings. If *args* is a sequence, it will
be converted to a string in a manner described in
@@ -335,16 +370,19 @@
A :exc:`ValueError` will be raised if :class:`Popen` is called with invalid
arguments.
-check_call() will raise :exc:`CalledProcessError`, if the called process returns
-a non-zero return code.
+:func:`check_call` and :func:`check_output` will raise
+:exc:`CalledProcessError` if the called process returns a non-zero return
+code.
Security
^^^^^^^^
-Unlike some other popen functions, this implementation will never call /bin/sh
-implicitly. This means that all characters, including shell metacharacters, can
-safely be passed to child processes.
+Unlike some other popen functions, this implementation will never call a
+system shell implicitly. This means that all characters, including shell
+metacharacters, can safely be passed to child processes. Obviously, if the
+shell is invoked explicitly, then it is the application's responsibility to
+all that all whitespace and metacharacters are quoted appropriately.
Popen Objects
@@ -582,14 +620,17 @@
.. note::
- All functions in this section fail (more or less) silently if the executed
- program cannot be found; this module raises an :exc:`OSError` exception. In
- addition, the replacements using :func:`check_output` will fail with a
+ All "a" functions in this section fail (more or less) silently if the
+ executed program cannot be found; the "b" replacements raise :exc:`OSError`
+ instead.
+
+ In addition, the replacements using :func:`check_output` will fail with a
:exc:`CalledProcessError` if the requested operation produces a non-zero
- return code.
+ return code. The output is still available as the ``output`` attribute of
+ the raised exception.
-In the following examples, we assume that the subprocess module is imported with
-"from subprocess import \*".
+In the following examples, we assume that the relevant functions have already
+been imported from the subprocess module.
Replacing /bin/sh shell backquote
@@ -617,8 +658,8 @@
The p1.stdout.close() call after starting the p2 is important in order for p1
to receive a SIGPIPE if p2 exits before p1.
-Alternatively, for trusted input, the shell's pipeline may still be used
-directly:
+Alternatively, for trusted input, the shell's own pipeline support may still
+be used directly:
output=`dmesg | grep hda`
# becomes
@@ -638,8 +679,6 @@
* Calling the program through the shell is usually not required.
-* It's easier to look at the :attr:`returncode` attribute than the exit status.
-
A more realistic example would look like this::
try:
@@ -784,6 +823,7 @@
* popen2 closes all file descriptors by default, but you have to specify
``close_fds=True`` with :class:`Popen`.
+
Notes
-----
--
Repository URL: http://hg.python.org/cpython
More information about the Python-checkins
mailing list