You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Documentation for sys.stdout encoding does not reflect the new Windows behavior in Python 3.6+ #74595
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee=Noneclosed_at=<Date2019-02-14.23:36:54.782>created_at=<Date2017-05-20.08:58:49.633>labels= ['easy', 'type-bug', '3.8', '3.7', 'OS-windows', 'docs']
title='Documentation for sys.stdout encoding does not reflect the new Windows behavior in Python 3.6+'updated_at=<Date2019-02-14.23:45:23.357>user='https://github.com/pfmoore'
The documentation for the encoding of sys.stdin/out/err (see https://docs.python.org/3.6/library/sys.html#sys.stdout) does not reflect the change in Python 3.6 on Windows to use the console Unicode APIs, and hence UTF-8 for the encoding.
The character encoding is platform-dependent. Non-Windows
platforms use the locale encoding (see
locale.getpreferredencoding()).
On Windows, UTF-8 is used for console character
devices (i.e. CON, CONIN$, and CONOUT$). However, this
can be overridden to use the console as a generic
character device by setting the environment variable
PYTHONLEGACYWINDOWSSTDIO before starting Python. Non-
character devices such as disk files and pipes use the
system locale encoding (i.e. the ANSI codepage).
Character devices such as NUL (i.e. isatty() returns
True) use the value of the console input and output
codepages at startup, respectively for stdin and
stdout/stderr. This defaults to the system locale
encoding if the process is not initially attached to a
console.
Under all platforms, you can override this value by
setting the PYTHONIOENCODING environment variable before
starting Python. However, for the Windows console, this
only applies when PYTHONLEGACYWINDOWSSTDIO is also set.
I discussed character devices mostly because of the NUL device. It could be surprising that Python dies on an encoding error when output is redirected to NUL:
C:\>chcp 1252
Active code page: 1252
C:\>python -c "print('\u20ac')" > nul
C:\>chcp 437
Active code page: 437
C:\>python -c "print('\u20ac')" > nul
Traceback (most recent call last):
File "<string>", line 1, in<module>
File "C:\Program Files\Python36\lib\encodings\cp437.py", line 19, in encode
return codecs.charmap_encode(input,self.errors,encoding_map)[0]
UnicodeEncodeError: 'charmap' codec can't encode character '\u20ac' in position 0:
character maps to <undefined>
Unix has a similar problem:
$LANG=C python3 -c 'print("\u20ac")'>/dev/null
Traceback (most recent call last):
File "<string>", line 1, in<module>UnicodeEncodeError: 'ascii' codec can't encode character '\u20ac' in position 0:
ordinal notinrange(128)
Except /dev/null isn't a TTY. Also, it's rare nowadays for the locale encoding in Unix systems to be something other than UTF-8.
It would be useful if we special-cased NUL like we do for the Windows console, but just to make it use the backslashreplace error handler. Unfortunately I don't know how to do that without calling NtQueryObject, for which ObjectNameInformation (1) can't be used because it's undocumented 1. GetFinalPathNameByHandle also can't be used because it requires file-system devices. As a crude workaround, we could lump together all non-console character devices (i.e. isatty() but not a console). That will affect serial devices, too, but I can't think of a good reason someone would redirect stdout or stderr to a COM port.
The proposed wording seems a bit over-complex to me. Maybe the following re-wording would be easier to understand?
The character encoding is platform-dependent. Non-Windows
platforms use the locale encoding (see
locale.getpreferredencoding()).
On Windows, UTF-8 is used for the console device. Non-character
devices such as disk files and pipes use the system locale
encoding (i.e. the ANSI codepage). Non-console character
devices such as NUL (i.e. where isatty() returns True) use the
value of the console input and output codepages at startup,
respectively for stdin and stdout/stderr. This defaults to the
system locale encoding if the process is not initially attached
to a console.
The special behaviour of the console can be overridden
by setting the environment variable PYTHONLEGACYWINDOWSSTDIO
before starting Python. In that case, the console codepages are
used as for any other character device.
Under all platforms, you can override this value by
setting the PYTHONIOENCODING environment variable before
starting Python. However, for the Windows console, this
only applies when PYTHONLEGACYWINDOWSSTDIO is also set.
New changeset 5723263 by Miss Islington (bot) (Lysandros Nikolaou) in branch 'master': bpo-30410: Documentation of sys.stdin/out/err update to reflect change in 3.6 (GH-10264) 5723263
New changeset b8bcec3 by Miss Islington (bot) in branch '3.7': bpo-30410: Documentation of sys.stdin/out/err update to reflect change in 3.6 (GH-10264) b8bcec3
Activity
pfmoore commentedon May 20, 2017
The documentation for the encoding of sys.stdin/out/err (see https://docs.python.org/3.6/library/sys.html#sys.stdout) does not reflect the change in Python 3.6 on Windows to use the console Unicode APIs, and hence UTF-8 for the encoding.
eryksun commentedon May 20, 2017
How about this?
zooba commentedon May 20, 2017
Looks great, though I wonder whether the rest of the paragraph after "Character devices such as NUL" would be more confusing than it's worth?
Can you create a PR? (And having links to the environment variable docs would be great.)
eryksun commentedon May 21, 2017
I discussed character devices mostly because of the NUL device. It could be surprising that Python dies on an encoding error when output is redirected to NUL:
Unix has a similar problem:
Except /dev/null isn't a TTY. Also, it's rare nowadays for the locale encoding in Unix systems to be something other than UTF-8.
It would be useful if we special-cased NUL like we do for the Windows console, but just to make it use the backslashreplace error handler. Unfortunately I don't know how to do that without calling NtQueryObject, for which ObjectNameInformation (1) can't be used because it's undocumented 1. GetFinalPathNameByHandle also can't be used because it requires file-system devices. As a crude workaround, we could lump together all non-console character devices (i.e. isatty() but not a console). That will affect serial devices, too, but I can't think of a good reason someone would redirect stdout or stderr to a COM port.
lysnikolaou commentedon Oct 28, 2018
Shall I create a PR for this?
zooba commentedon Oct 29, 2018
Please do!
lysnikolaou commentedon Nov 30, 2018
Ping.
pfmoore commentedon Nov 30, 2018
The proposed wording seems a bit over-complex to me. Maybe the following re-wording would be easier to understand?
lysnikolaou commentedon Dec 2, 2018
I updated the PR with the new wording by Paul, since I found it easier to understand as well.
miss-islington commentedon Feb 14, 2019
New changeset 5723263 by Miss Islington (bot) (Lysandros Nikolaou) in branch 'master':
bpo-30410: Documentation of sys.stdin/out/err update to reflect change in 3.6 (GH-10264)
5723263
Mariatta commentedon Feb 14, 2019
Fixed in 3.8 and 3.7.
Thanks!
miss-islington commentedon Feb 14, 2019
New changeset b8bcec3 by Miss Islington (bot) in branch '3.7':
bpo-30410: Documentation of sys.stdin/out/err update to reflect change in 3.6 (GH-10264)
b8bcec3