If *encoding* or *errors* are specified, or *text* is true, the file objects
*stdin*, *stdout* and *stderr* are opened in text mode with the specified
- encoding and *errors*, as described above in :ref:`frequently-used-arguments`.
+ *encoding* and *errors*, as described above in :ref:`frequently-used-arguments`.
The *universal_newlines* argument is equivalent to *text* and is provided
for backwards compatibility. By default, file objects are opened in binary mode.
none of the guarantees described above regarding security and exception
handling consistency are valid for these functions.
-.. function:: getstatusoutput(cmd)
+.. function:: getstatusoutput(cmd, *, encoding=None, errors=None)
Return ``(exitcode, output)`` of executing *cmd* in a shell.
Execute the string *cmd* in a shell with :meth:`Popen.check_output` and
- return a 2-tuple ``(exitcode, output)``. The locale encoding is used;
+ return a 2-tuple ``(exitcode, output)``.
+ *encoding* and *errors* are used to decode output;
see the notes on :ref:`frequently-used-arguments` for more details.
A trailing newline is stripped from the output.
as it did in Python 3.3.3 and earlier. exitcode has the same value as
:attr:`~Popen.returncode`.
+ .. versionadded:: 3.11
+ Added *encoding* and *errors* arguments.
-.. function:: getoutput(cmd)
+.. function:: getoutput(cmd, *, encoding=None, errors=None)
Return output (stdout and stderr) of executing *cmd* in a shell.
.. versionchanged:: 3.3.4
Windows support added
+ .. versionadded:: 3.11
+ Added *encoding* and *errors* arguments.
+
Notes
-----
except NameError:
def getpreferredencoding(do_setlocale=True):
"""Return the charset that the user is likely using."""
+ if sys.flags.warn_default_encoding:
+ import warnings
+ warnings.warn(
+ "UTF-8 Mode affects locale.getpreferredencoding(). Consider locale.getencoding() instead.",
+ EncodingWarning, 2)
if sys.flags.utf8_mode:
return 'utf-8'
return getencoding()
def getpreferredencoding(do_setlocale=True):
"""Return the charset that the user is likely using,
according to the system configuration."""
+
+ if sys.flags.warn_default_encoding:
+ import warnings
+ warnings.warn(
+ "UTF-8 Mode affects locale.getpreferredencoding(). Consider locale.getencoding() instead.",
+ EncodingWarning, 2)
if sys.flags.utf8_mode:
return 'utf-8'
import builtins
import errno
import io
+import locale
import os
import time
import signal
return args
+def _text_encoding():
+ # Return default text encoding and emit EncodingWarning if
+ # sys.flags.warn_default_encoding is true.
+ if sys.flags.warn_default_encoding:
+ f = sys._getframe()
+ filename = f.f_code.co_filename
+ stacklevel = 2
+ while f := f.f_back:
+ if f.f_code.co_filename != filename:
+ break
+ stacklevel += 1
+ warnings.warn("'encoding' argument not specified.",
+ EncodingWarning, stacklevel)
+
+ if sys.flags.utf8_mode:
+ return "utf-8"
+ else:
+ return locale.getencoding()
+
+
def call(*popenargs, timeout=None, **kwargs):
"""Run command with arguments. Wait for command to complete or
timeout, then return the returncode attribute.
# Various tools for executing commands and looking at their output and status.
#
-def getstatusoutput(cmd):
+def getstatusoutput(cmd, *, encoding=None, errors=None):
"""Return (exitcode, output) of executing cmd in a shell.
Execute the string 'cmd' in a shell with 'check_output' and
(-15, '')
"""
try:
- data = check_output(cmd, shell=True, text=True, stderr=STDOUT)
+ data = check_output(cmd, shell=True, text=True, stderr=STDOUT,
+ encoding=encoding, errors=errors)
exitcode = 0
except CalledProcessError as ex:
data = ex.output
data = data[:-1]
return exitcode, data
-def getoutput(cmd):
+def getoutput(cmd, *, encoding=None, errors=None):
"""Return output (stdout or stderr) of executing cmd in a shell.
Like getstatusoutput(), except the exit status is ignored and the return
>>> subprocess.getoutput('ls /bin/ls')
'/bin/ls'
"""
- return getstatusoutput(cmd)[1]
+ return getstatusoutput(cmd, encoding=encoding, errors=errors)[1]
+
def _use_posix_spawn():
errread = msvcrt.open_osfhandle(errread.Detach(), 0)
self.text_mode = encoding or errors or text or universal_newlines
-
- # PEP 597: We suppress the EncodingWarning in subprocess module
- # for now (at Python 3.10), because we focus on files for now.
- # This will be changed to encoding = io.text_encoding(encoding)
- # in the future.
if self.text_mode and encoding is None:
- self.encoding = encoding = "locale"
+ self.encoding = encoding = _text_encoding()
# How long to resume waiting on a child after the first ^C.
# There is no right value for this. The purpose is to be polite
msg="TimeoutExpired was delayed! Bad traceback:\n```\n"
f"{stacks}```")
+ def test_encoding_warning(self):
+ code = textwrap.dedent("""\
+ from subprocess import *
+ args = ["echo", "hello"]
+ run(args, text=True)
+ check_output(args, text=True)
+ """)
+ cp = subprocess.run([sys.executable, "-Xwarn_default_encoding", "-c", code],
+ capture_output=True)
+ lines = cp.stderr.splitlines()
+ self.assertEqual(len(lines), 2)
+ self.assertTrue(lines[0].startswith(b"<string>:3: EncodingWarning: "))
+ self.assertTrue(lines[1].startswith(b"<string>:4: EncodingWarning: "))
+
def _get_test_grp_name():
for name_group in ('staff', 'nogroup', 'grp', 'nobody', 'nfsnobody'):
--- /dev/null
+Add *encoding* and *errors* arguments to :func:`subprocess.getoutput` and
+:func:`subprocess.getstatusoutput`.