2019-06-05 08:09:19 -04:00
|
|
|
PEP: 597
|
2019-06-11 23:22:09 -04:00
|
|
|
Title: Add PYTHONTEXTENCODING environment variable
|
2019-06-05 08:09:19 -04:00
|
|
|
Author: Inada Naoki <songofacandy@gmail.com>
|
|
|
|
Status: Draft
|
|
|
|
Type: Standards Track
|
|
|
|
Content-Type: text/x-rst
|
|
|
|
Created: 05-Jun-2019
|
|
|
|
Python-Version: 3.9
|
|
|
|
|
|
|
|
|
|
|
|
Abstract
|
|
|
|
========
|
|
|
|
|
|
|
|
Currently, ``TextIOWrapper`` uses ``locale.getpreferredencoding(False)``
|
2019-06-11 23:22:09 -04:00
|
|
|
(hereinafter called "locale encoding") when ``encoding`` is not
|
|
|
|
specified.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
This PEP proposes adding ``PYTHONTEXTENCODING`` environment
|
|
|
|
variable to override the default text encoding since Python 3.9.
|
|
|
|
|
|
|
|
The goal of this PEP is providing "UTF-8 by default" experience to
|
|
|
|
Windows users, because macOS, Linux, Android, iOS users use UTF-8
|
|
|
|
by default already.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
|
|
|
|
|
|
|
Motivation
|
|
|
|
==========
|
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
UTF-8 is the best encoding for saving unicode text
|
|
|
|
--------------------------------------------------
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
String in Python 3 is unicode. Encoding valid unicode strings with
|
|
|
|
UTF-8 should not fail.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
On the other hand, most locale encoding used in Windows can not
|
|
|
|
save all valid unicode string. It will cause UnicodeEncodeError
|
|
|
|
or it may not round-trip. User may lost their data in such case.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
UTF-8 is the best encoding for saving text when user don't specify
|
|
|
|
any encoding.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
|
|
|
|
2019-06-06 09:19:01 -04:00
|
|
|
Using UTF-8 by default is easier on new programmers
|
|
|
|
---------------------------------------------------
|
2019-06-05 08:09:19 -04:00
|
|
|
|
|
|
|
Python is one of the most popular first programming languages.
|
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
New programmers may not know about encoding. When they download text
|
|
|
|
data written in UTF-8 from the Internet, they are forced to learn
|
|
|
|
about encoding.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
|
|
|
Popular text editors like VS Code or Atom use UTF-8 by default.
|
2019-06-11 23:22:09 -04:00
|
|
|
Even Microsoft Notepad uses UTF-8 by default since the Windows 10 May
|
|
|
|
2019 Update. (Note that Python 3.9 will be released in 2021.)
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-06 09:19:01 -04:00
|
|
|
Additionally, the default encoding of Python source files is UTF-8.
|
2019-06-05 08:09:19 -04:00
|
|
|
We can assume new Python programmers who don't know about encoding
|
|
|
|
use editors which use UTF-8 by default.
|
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
It would be nice if new programmers are not forced to learn about
|
|
|
|
encoding until they need to handle text files encoded in encoding
|
|
|
|
other than UTF-8.
|
|
|
|
|
|
|
|
|
|
|
|
People assume it is always UTF-8
|
|
|
|
--------------------------------
|
|
|
|
|
|
|
|
Package authors using macOS or Linux may forget that the default
|
|
|
|
encoding is not always UTF-8.
|
|
|
|
|
|
|
|
For example, ``long_description = open("README.md").read()`` in
|
|
|
|
``setup.py`` is a common mistake. If there is at least one emoji or
|
|
|
|
any other non-ASCII character in the ``README.md`` file, many Windows
|
|
|
|
users cannot install the package due to a ``UnicodeDecodeError``.
|
|
|
|
|
|
|
|
|
|
|
|
Consistent with default encoding
|
|
|
|
--------------------------------
|
|
|
|
|
|
|
|
Python has ``sys.defaultencoding()`` which is always "UTF-8".
|
|
|
|
``str.encode()`` uses "UTF-8" when encoding is omitted.
|
|
|
|
|
|
|
|
Using "UTF-8" for text files are consistent with it. It makes Python
|
|
|
|
more easy to learn language.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
|
|
|
|
|
|
|
Specification
|
|
|
|
=============
|
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
``PYTHONTEXTENCODING`` environment variable
|
|
|
|
-------------------------------------------
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
``PYTHONTEXTENCODING`` environment variable can be used to specify the
|
|
|
|
default text encoding.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
Unlike ``PYTHONIOENCODING``, it doesn't accept error handler.
|
|
|
|
``PYTHONIOENCODING`` support it because changing error handler of
|
|
|
|
stdio was difficult. But it is not true for regular files.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
``sys.gettextencoding()``
|
|
|
|
-------------------------
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
When ``PYTHONTEXTENCODING`` is specified, this function return it.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
When it is not specified, this function returns
|
|
|
|
``locale.getpreferredencoding(False)``.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
``encoding="locale"`` option
|
|
|
|
----------------------------
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
``TextIOWrapper`` now accepts ``encoding="locale"`` option.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
"locale" is not real encoding or alias.
|
|
|
|
This is just a shortcut of
|
|
|
|
``encoding=locale.getpreferredencoding(False)``.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
Changes in stdlibs
|
|
|
|
------------------
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
``TextIOWrapper`` uses ``sys.gettextencoding()`` where
|
|
|
|
``locale.getpreferredencoding(False)`` is used.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
But ``stdin``, ``stdout``, and ``stderr`` continue to respect
|
|
|
|
locale encoding as well. ``PYTHONIOENCODING`` can be used to
|
2019-06-25 00:58:50 -04:00
|
|
|
override their encoding.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
Pipes and TTY should use the "locale" encoding. UTF-8 mode [1]_
|
|
|
|
can be used to override these encoding:
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
* ``subprocess`` and ``os.popen`` use the "locale" encoding because
|
|
|
|
the subprocess will use the locale encoding.
|
|
|
|
* ``getpass.getpass`` uses the "locale" encoding when using TTY.
|
|
|
|
|
|
|
|
All other code using the default encoding are not modified.
|
|
|
|
They can be overridden by ``PYTHONTEXTENCODING``.
|
|
|
|
This is an incomplete list:
|
|
|
|
|
|
|
|
* ``lzma.open``, ``gzip.open``, ``bz2.open``, ``ZipFile.read_text``
|
|
|
|
* ``socket.makefile``
|
|
|
|
* ``tempfile.TemporaryFile``, ``tempfile.NamedTemporaryFile``
|
|
|
|
* ``trace.CoverageResults.write_results_file``
|
2019-06-05 08:09:19 -04:00
|
|
|
|
|
|
|
|
|
|
|
Rationale
|
|
|
|
=========
|
|
|
|
|
|
|
|
Why not just enable UTF-8 mode by default?
|
|
|
|
------------------------------------------
|
|
|
|
|
|
|
|
This PEP is not mutually exclusive to UTF-8 mode.
|
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
If we enable UTF-8 mode by default, even people using Windows will
|
|
|
|
forget the default encoding is not always UTF-8. More scripts will
|
|
|
|
be written assuming the default encoding is UTF-8.
|
|
|
|
|
|
|
|
So changing the default encoding of text files to UTF-8 would be
|
|
|
|
better even if UTF-8 mode is enabled by default at some point.
|
|
|
|
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
Why is "locale" not an alias codec?
|
|
|
|
-----------------------------------
|
|
|
|
|
|
|
|
For backward compatibility, ``io.TextIOWrapper`` calls
|
|
|
|
``locale.getpreferredencoding(False)`` every time when
|
|
|
|
``encoding="locale"`` is specified.
|
|
|
|
|
|
|
|
It respects changing locale after Python startup.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
|
|
|
|
|
|
|
Why not change std(in|out|err) encoding too?
|
|
|
|
--------------------------------------------
|
|
|
|
|
2019-06-06 09:19:01 -04:00
|
|
|
Even when the locale encoding is not UTF-8, there can be many UTF-8
|
|
|
|
text files. These files could be downloaded from the Internet or
|
|
|
|
written by modern text editors.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-06 09:19:01 -04:00
|
|
|
On the other hand, terminal encoding is assumed to be the same as
|
|
|
|
locale encoding. And other tools are assumed to read and write the
|
|
|
|
locale encoding as well.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
std(in|out|err) are likely to be connected to a terminal or other
|
|
|
|
tools. So the locale encoding should be respected.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
Anyway, ``PYTHONIOENCODING`` can be used to change these encodings.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
Reference Implementation
|
|
|
|
========================
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
To be written.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
Rejected Ideas
|
|
|
|
==============
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
Change the default text encoding
|
|
|
|
--------------------------------
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
Previous version of this PEP tried to change the default encoding
|
|
|
|
to UTF-8.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
But we should have deprecation period long enough. Between the
|
|
|
|
deprecation period, users can not change the default text encoding.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-25 00:58:50 -04:00
|
|
|
And there are many difficulty there:
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
* Omitting ``encoding`` option is very common.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
* If we raise ``DeprecationWarning`` always, it will be too noisy.
|
|
|
|
* We can not assume how user use it. Complicated heuritics may be
|
|
|
|
needed to raise ``DeprecationWarning`` only when it is really
|
|
|
|
needed.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
* Users of legacy systems may dismiss warning.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
* They may not check the warning.
|
|
|
|
* They may upgrade Python from 2.7 after 2020.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
Additionally, Microsoft is improving UTF-8 support of Windows 10
|
|
|
|
recently.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
There are no public plan for future UTF-8 support yet. But Python may
|
|
|
|
be able to change the default encoding without painful deprecation
|
|
|
|
period in the future.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
Open Issues
|
|
|
|
===========
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
Easy way to set ``PYTHONTEXTENCODING``
|
|
|
|
--------------------------------------
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
UTF-8 is the best encoding for new users. But setting environment
|
|
|
|
variables is not easy enough to new users.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
It would be helpfule if Python on Windows can provide easy way to set
|
|
|
|
``PYTHONTEXTENCODING=UTF-8`` even after Python is installed.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
Commandline option
|
|
|
|
------------------
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
If there is reasonable use case for changing default text encoding
|
|
|
|
per process, command line option should be considered.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
C-API
|
|
|
|
-----
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
The default text encoding should be able to configured from C.
|
|
|
|
This will be considered when writing reference Implementation.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
2019-06-11 23:22:09 -04:00
|
|
|
Additionally, C-API like ``PySys_GetTextEncoding()`` should be
|
|
|
|
considered too.
|
2019-06-05 08:09:19 -04:00
|
|
|
|
|
|
|
|
|
|
|
References
|
|
|
|
==========
|
|
|
|
|
2019-06-12 03:41:36 -04:00
|
|
|
.. [1] PEP 540, Add a new UTF-8 Mode
|
2019-06-11 23:22:09 -04:00
|
|
|
(https://www.python.org/dev/peps/pep-0540/)
|
|
|
|
|
2019-06-05 08:09:19 -04:00
|
|
|
|
|
|
|
Copyright
|
|
|
|
=========
|
|
|
|
|
|
|
|
This document has been placed in the public domain.
|
|
|
|
|
|
|
|
..
|
|
|
|
Local Variables:
|
|
|
|
mode: indented-text
|
|
|
|
indent-tabs-mode: nil
|
|
|
|
sentence-end-double-space: t
|
|
|
|
fill-column: 70
|
|
|
|
coding: utf-8
|
|
|
|
End:
|