PEP 587 version 5 (#1086)

* Add "Experimental Multi-Phase Initialization API" section
* Add PyPreConfig._config_init private field.
* Rename PyInitError to PyStatus.
* Rename PyInitError_Failed() to PyStatus_Exception()
* Rename Py_ExitInitError() to Py_ExitStatusException()
* Fix Python Configuration default values: isolated=0
  and use_environment=1, instead of -1.
* Document isolated field and #ifdef MS_WINDOWS
* Define path conf function
This commit is contained in:
Victor Stinner 2019-05-24 21:21:05 +02:00 committed by GitHub
parent 74f0fb256d
commit fcdd72d719
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 284 additions and 104 deletions

View File

@ -107,7 +107,7 @@ macros.
New structures:
* ``PyConfig``
* ``PyInitError``
* ``PyStatus``
* ``PyPreConfig``
* ``PyWideStringList``
@ -121,19 +121,19 @@ New functions:
* ``PyConfig_SetBytesArgv(config, argc, argv)``
* ``PyConfig_SetBytesString(config, config_str, str)``
* ``PyConfig_SetString(config, config_str, str)``
* ``PyInitError_Error(err_msg)``
* ``PyInitError_Exit(exitcode)``
* ``PyInitError_Failed(err)``
* ``PyInitError_IsError(err)``
* ``PyInitError_IsExit(err)``
* ``PyInitError_NoMemory()``
* ``PyInitError_Ok()``
* ``PyPreConfig_InitIsolatedConfig(preconfig)``
* ``PyPreConfig_InitPythonConfig(preconfig)``
* ``PyStatus_Error(err_msg)``
* ``PyStatus_Exception(status)``
* ``PyStatus_Exit(exitcode)``
* ``PyStatus_IsError(status)``
* ``PyStatus_IsExit(status)``
* ``PyStatus_NoMemory()``
* ``PyStatus_Ok()``
* ``PyWideStringList_Append(list, item)``
* ``PyWideStringList_Insert(list, index, item)``
* ``Py_BytesMain(argc, argv)``
* ``Py_ExitInitError(err)``
* ``Py_ExitStatusException(status)``
* ``Py_InitializeFromConfig(config)``
* ``Py_PreInitialize(preconfig)``
* ``Py_PreInitializeFromArgs(preconfig, argc, argv)``
@ -159,45 +159,45 @@ PyWideStringList
Methods:
* ``PyInitError PyWideStringList_Append(PyWideStringList *list, const wchar_t *item)``:
* ``PyStatus PyWideStringList_Append(PyWideStringList *list, const wchar_t *item)``:
Append *item* to *list*.
* ``PyInitError PyWideStringList_Insert(PyWideStringList *list, Py_ssize_t index, const wchar_t *item)``:
* ``PyStatus PyWideStringList_Insert(PyWideStringList *list, Py_ssize_t index, const wchar_t *item)``:
Insert *item* into *list* at *index*. If *index* is greater than
*list* length, just append *item* to *list*.
If *length* is non-zero, *items* must be non-NULL and all strings must
be non-NULL.
PyInitError
-----------
PyStatus
--------
``PyInitError`` is a structure to store an error message or an exit code
for the Python Initialization. For an error, it stores the C function
name which created the error.
``PyStatus`` is a structure to store the status of an initialization
function: success, error or exit. For an error, it can store the C
function name which created the error.
Example::
PyInitError alloc(void **ptr, size_t size)
PyStatus alloc(void **ptr, size_t size)
{
*ptr = PyMem_RawMalloc(size);
if (*ptr == NULL) {
return PyInitError_NoMemory();
return PyStatus_NoMemory();
}
return PyInitError_Ok();
return PyStatus_Ok();
}
int main(int argc, char **argv)
{
void *ptr;
PyInitError err = alloc(&ptr, 16);
if (PyInitError_Failed(err)) {
Py_ExitInitError(err);
PyStatus status = alloc(&ptr, 16);
if (PyStatus_Exception(status)) {
Py_ExitStatusException(status);
}
PyMem_Free(ptr);
return 0;
}
``PyInitError`` fields:
``PyStatus`` fields:
* ``exitcode`` (``int``):
Argument passed to ``exit()``.
@ -207,22 +207,29 @@ Example::
Name of the function which created an error, can be ``NULL``.
* private ``_type`` field: for internal usage only.
Functions to create an error:
Functions to create a status:
* ``PyInitError_Ok()``: Success.
* ``PyInitError_Error(err_msg)``: Initialization error with a message.
* ``PyInitError_NoMemory()``: Memory allocation failure (out of memory).
* ``PyInitError_Exit(exitcode)``: Exit Python with the specified exit code.
* ``PyStatus_Ok()``: Success.
* ``PyStatus_Error(err_msg)``: Initialization error with a message.
* ``PyStatus_NoMemory()``: Memory allocation failure (out of memory).
* ``PyStatus_Exit(exitcode)``: Exit Python with the specified exit code.
Functions to handle an error:
Functions to handle a status:
* ``PyStatus_Exception(status)``: Is the result an error or an exit?
If true, the exception must be handled; by calling
``Py_ExitStatusException(status)`` for example.
* ``PyStatus_IsError(status)``: Is the result an error?
* ``PyStatus_IsExit(status)``: Is the result an exit?
* ``Py_ExitStatusException(status)``: Call ``exit(exitcode)`` if *status*
is an exit. Print the error messageand exit with a non-zero exit code
if *status* is an error. Must only be called if
``PyStatus_Exception(status)`` is true.
.. note::
Internally, Python uses macros which set ``PyStatus.func``,
whereas functions to create a status set ``func`` to ``NULL``.
* ``PyInitError_Failed(err)``: Is the result an error or an exit?
* ``PyInitError_IsError(err)``: Is the result an error?
* ``PyInitError_IsExit(err)``: Is the result an exit?
* ``Py_ExitInitError(err)``: Call ``exit(exitcode)`` if *err* is an
exit, print the error and exit if *err* is an error. Must only be
called with an error and an exit: if ``PyInitError_Failed(err)`` is
true.
Preinitialization with PyPreConfig
----------------------------------
@ -240,9 +247,9 @@ Example using the preinitialization to enable the UTF-8 Mode::
preconfig.utf8_mode = 1;
PyInitError err = Py_PreInitialize(&preconfig);
if (PyInitError_Failed(err)) {
Py_ExitInitError(err);
PyStatus status = Py_PreInitialize(&preconfig);
if (PyStatus_Exception(status)) {
Py_ExitStatusException(status);
}
/* at this point, Python will speak UTF-8 */
@ -258,12 +265,12 @@ Function to initialize a pre-configuration:
Functions to preinitialization Python:
* ``PyInitError Py_PreInitialize(const PyPreConfig *preconfig)``
* ``PyInitError Py_PreInitializeFromBytesArgs(const PyPreConfig *preconfig, int argc, char * const *argv)``
* ``PyInitError Py_PreInitializeFromArgs(const PyPreConfig *preconfig, int argc, wchar_t * const * argv)``
* ``PyStatus Py_PreInitialize(const PyPreConfig *preconfig)``
* ``PyStatus Py_PreInitializeFromBytesArgs(const PyPreConfig *preconfig, int argc, char * const *argv)``
* ``PyStatus Py_PreInitializeFromArgs(const PyPreConfig *preconfig, int argc, wchar_t * const * argv)``
The caller is responsible to handle error or exit using
``PyInitError_Failed()`` and ``Py_ExitInitError()``.
The caller is responsible to handle exceptions (error or exit) using
``PyStatus_Exception()`` and ``Py_ExitStatusException()``.
If Python is initialized with command line arguments, the command line
arguments must also be passed to preinitialize Python, since they have
@ -279,11 +286,14 @@ an effect on the pre-configuration like encodings. For example, the
* ``PYMEM_ALLOCATOR_NOT_SET`` (``0``): don't change memory allocators
(use defaults)
* ``PYMEM_ALLOCATOR_DEFAULT`` (``1``): default memory allocators
* ``PYMEM_ALLOCATOR_DEBUG`` (``2``): enable debug hooks
* ``PYMEM_ALLOCATOR_DEBUG`` (``2``): default memory allocators with
debug hooks
* ``PYMEM_ALLOCATOR_MALLOC`` (``3``): force usage of ``malloc()``
* ``PYMEM_ALLOCATOR_MALLOC_DEBUG`` (``4``): ``malloc()`` with debug hooks
* ``PYMEM_ALLOCATOR_MALLOC_DEBUG`` (``4``): force usage of
``malloc()`` with debug hooks
* ``PYMEM_ALLOCATOR_PYMALLOC`` (``5``): Python "pymalloc" allocator
* ``PYMEM_ALLOCATOR_PYMALLOC_DEBUG`` (``6``): pymalloc with debug hooks
* ``PYMEM_ALLOCATOR_PYMALLOC_DEBUG`` (``6``): Python "pymalloc"
allocator with debug hooks
* Note: ``PYMEM_ALLOCATOR_PYMALLOC`` and
``PYMEM_ALLOCATOR_PYMALLOC_DEBUG`` are not supported if Python is
configured using ``--without-pymalloc``
@ -300,7 +310,7 @@ an effect on the pre-configuration like encodings. For example, the
See ``PyConfig.dev_mode``.
* ``isolated`` (``int``):
See ``PyConfig.isolated``.
* ``legacy_windows_fs_encoding`` (``int``):
* ``legacy_windows_fs_encoding`` (``int``, Windows only):
If non-zero, disable UTF-8 Mode, set the Python filesystem encoding to
``mbcs``, set the filesystem error handler to ``replace``.
* ``parse_argv`` (``int``):
@ -313,11 +323,15 @@ an effect on the pre-configuration like encodings. For example, the
* ``utf8_mode`` (``int``):
If non-zero, enable the UTF-8 mode.
The ``legacy_windows_fs_encoding`` is only available on Windows.
The ``legacy_windows_fs_encoding`` field is only available on Windows.
``#ifdef MS_WINDOWS`` macro can be used for Windows specific code.
There is also a private field, for internal use only,
``_config_version`` (``int``): the configuration version, used
for ABI compatibility.
``PyPreConfig`` private fields, for internal use only:
* ``_config_version`` (``int``):
Configuration version, used for ABI compatibility.
* ``_config_init`` (``int``):
Function used to initalize ``PyConfig``, used for preinitialization.
``PyMem_SetAllocator()`` can be called after ``Py_PreInitialize()`` and
before ``Py_InitializeFromConfig()`` to install a custom memory
@ -339,23 +353,23 @@ Example setting the program name::
void init_python(void)
{
PyInitError err;
PyStatus status;
PyConfig config;
err = PyConfig_InitPythonConfig(&config);
if (PyInitError_Failed(err)) {
status = PyConfig_InitPythonConfig(&config);
if (PyStatus_Exception(status)) {
goto fail;
}
/* Set the program name. Implicitly preinitialize Python. */
err = PyConfig_SetString(&config, &config.program_name,
status = PyConfig_SetString(&config, &config.program_name,
L"/path/to/my_program");
if (PyInitError_Failed(err)) {
if (PyStatus_Exception(status)) {
goto fail;
}
err = Py_InitializeFromConfig(&config);
if (PyInitError_Failed(err)) {
status = Py_InitializeFromConfig(&config);
if (PyStatus_Exception(status)) {
goto fail;
}
PyConfig_Clear(&config);
@ -363,29 +377,29 @@ Example setting the program name::
fail:
PyConfig_Clear(&config);
Py_ExitInitError(err);
Py_ExitStatusException(status);
}
``PyConfig`` methods:
* ``PyInitError PyConfig_InitPythonConfig(PyConfig *config)``
* ``PyStatus PyConfig_InitPythonConfig(PyConfig *config)``
Initialize configuration with `Python Configuration`_.
* ``PyInitError PyConfig_InitIsolatedConfig(PyConfig *config)``:
* ``PyStatus PyConfig_InitIsolatedConfig(PyConfig *config)``:
Initialize configuration with `Isolated Configuration`_.
* ``PyInitError PyConfig_SetString(PyConfig *config, wchar_t * const *config_str, const wchar_t *str)``:
* ``PyStatus PyConfig_SetString(PyConfig *config, wchar_t * const *config_str, const wchar_t *str)``:
Copy the wide character string *str* into ``*config_str``.
Preinitialize Python if needed.
* ``PyInitError PyConfig_SetBytesString(PyConfig *config, wchar_t * const *config_str, const char *str)``:
* ``PyStatus PyConfig_SetBytesString(PyConfig *config, wchar_t * const *config_str, const char *str)``:
Decode *str* using ``Py_DecodeLocale()`` and set the result into
``*config_str``.
Preinitialize Python if needed.
* ``PyInitError PyConfig_SetArgv(PyConfig *config, int argc, wchar_t * const *argv)``:
* ``PyStatus PyConfig_SetArgv(PyConfig *config, int argc, wchar_t * const *argv)``:
Set command line arguments from wide character strings.
Preinitialize Python if needed.
* ``PyInitError PyConfig_SetBytesArgv(PyConfig *config, int argc, char * const *argv)``:
* ``PyStatus PyConfig_SetBytesArgv(PyConfig *config, int argc, char * const *argv)``:
Set command line arguments: decode bytes using ``Py_DecodeLocale()``.
Preinitialize Python if needed.
* ``PyInitError PyConfig_Read(PyConfig *config)``:
* ``PyStatus PyConfig_Read(PyConfig *config)``:
Read all Python configuration. Fields which are already initialized
are left unchanged.
Preinitialize Python if needed.
@ -409,11 +423,13 @@ preinitialization configuration depends on command line arguments (if
Functions to initialize Python:
* ``PyInitError Py_InitializeFromConfig(const PyConfig *config)``:
* ``PyStatus Py_InitializeFromConfig(const PyConfig *config)``:
Initialize Python from *config* configuration.
The caller of these methods and functions is responsible to handle error
or exit using ``PyInitError_Failed()`` and ``Py_ExitInitError()``.
The caller of these methods and functions is responsible to handle
exceptions (error or exit) using ``PyStatus_Exception()`` and
``Py_ExitStatusException()``.
``PyConfig`` fields:
@ -465,6 +481,16 @@ or exit using ``PyInitError_Failed()`` and ``Py_ExitInitError()``.
Install signal handlers?
* ``interactive`` (``int``):
Interactive mode.
* ``isolated`` (``int``):
If greater than 0, enable isolated mode:
* ``sys.path`` contains neither the script's directory (computed from
``argv[0]`` or the current directory) nor the user's site-packages
directory.
* Python REPL doesn't import ``readline`` nor enable default readline
configuration on interactive prompts.
* Set ``use_environment`` and ``user_site_directory`` are set to 0.
* ``legacy_windows_stdio`` (``int``, Windows only):
If non-zero, use ``io.FileIO`` instead of ``WindowsConsoleIO`` for
``sys.stdin``, ``sys.stdout`` and ``sys.stderr``.
@ -531,6 +557,9 @@ or exit using ``PyInitError_Failed()`` and ``Py_ExitInitError()``.
* ``xoptions`` (``PyWideStringList``):
``sys._xoptions``.
The ``legacy_windows_stdio`` field is only available on Windows.
``#ifdef MS_WINDOWS`` macro can be used for Windows specific code.
If ``parse_argv`` is non-zero, ``argv`` arguments are parsed the same
way the regular Python parses command line arguments, and Python
arguments are stripped from ``argv``: see `Command Line Arguments`_.
@ -553,13 +582,13 @@ Options`_.
More complete example modifying the default configuration, read the
configuration, and then override some parameters::
PyInitError init_python(const char *program_name)
PyStatus init_python(const char *program_name)
{
PyInitError err;
PyStatus status;
PyConfig config;
err = PyConfig_InitPythonConfig(&config);
if (PyInitError_Failed(err)) {
status = PyConfig_InitPythonConfig(&config);
if (PyStatus_Exception(status)) {
goto done;
}
@ -567,44 +596,44 @@ configuration, and then override some parameters::
(decode byte string from the locale encoding).
Implicitly preinitialize Python. */
err = PyConfig_SetBytesString(&config, &config.program_name,
status = PyConfig_SetBytesString(&config, &config.program_name,
program_name);
if (PyInitError_Failed(err)) {
if (PyStatus_Exception(status)) {
goto done;
}
/* Read all configuration at once */
err = PyConfig_Read(&config);
if (PyInitError_Failed(err)) {
status = PyConfig_Read(&config);
if (PyStatus_Exception(status)) {
goto done;
}
/* Append our custom search path to sys.path */
err = PyWideStringList_Append(&config.module_search_paths,
status = PyWideStringList_Append(&config.module_search_paths,
L"/path/to/more/modules");
if (PyInitError_Failed(err)) {
if (PyStatus_Exception(status)) {
goto done;
}
/* Override executable computed by PyConfig_Read() */
err = PyConfig_SetString(&config, &config.executable,
status = PyConfig_SetString(&config, &config.executable,
L"/path/to/my_executable");
if (PyInitError_Failed(err)) {
if (PyStatus_Exception(status)) {
goto done;
}
err = Py_InitializeFromConfig(&config);
status = Py_InitializeFromConfig(&config);
done:
PyConfig_Clear(&config);
return err;
return status;
}
.. note::
``PyImport_FrozenModules``, ``PyImport_AppendInittab()`` and
``PyImport_ExtendInittab()`` functions are still relevant and
continue to work as previously. They should be set or called
before the Python initialization.
continue to work as previously. They should be set or called after
Python preinitialization and before the Python initialization.
Isolated Configuration
@ -644,10 +673,10 @@ Example of customized Python always running in isolated mode::
int main(int argc, char **argv)
{
PyConfig config;
PyInitError err;
PyStatus status;
err = PyConfig_InitPythonConfig(&config);
if (PyInitError_Failed(err)) {
status = PyConfig_InitPythonConfig(&config);
if (PyStatus_Exception(status)) {
goto fail;
}
@ -655,13 +684,13 @@ Example of customized Python always running in isolated mode::
/* Decode command line arguments.
Implicitly preinitialize Python (in isolated mode). */
err = PyConfig_SetBytesArgv(&config, argc, argv);
if (PyInitError_Failed(err)) {
status = PyConfig_SetBytesArgv(&config, argc, argv);
if (PyStatus_Exception(status)) {
goto fail;
}
err = Py_InitializeFromConfig(&config);
if (PyInitError_Failed(err)) {
status = Py_InitializeFromConfig(&config);
if (PyStatus_Exception(status)) {
goto fail;
}
PyConfig_Clear(&config);
@ -670,12 +699,12 @@ Example of customized Python always running in isolated mode::
fail:
PyConfig_Clear(&config);
if (!PyInitError_IsExit(err)) {
/* Display the error message and exit the process with
non-zero exit code */
Py_ExitInitError(err);
if (PyStatus_IsExit(status)) {
return status.exitcode;
}
return err.exitcode;
/* Display the error message and exit the process with
non-zero exit code */
Py_ExitStatusException(status);
}
This example is a basic implementation of the "System Python Executable"
@ -700,6 +729,11 @@ Path Configuration
* ``prefix``
* ``module_search_paths_set``, ``module_search_paths``
If at least one "output field" is not set, Python computes the path
configuration to fill unset fields. If ``module_search_paths_set`` is
equal to 0, ``module_search_paths`` is overriden and
``module_search_paths_set`` is set to 1.
It is possible to completely ignore the function computing the default
path configuration by setting explicitly all path configuration output
fields listed above. A string is considered as set even if it's an empty
@ -713,9 +747,22 @@ path configuration (Unix only, Windows does not log any warning).
If ``base_prefix`` or ``base_exec_prefix`` fields are not set, they
inherit their value from ``prefix`` and ``exec_prefix`` respectively.
``Py_RunMain()`` and ``Py_Main()`` modify ``sys.path``:
* If ``run_filename`` is set and is a directory which contains a
``__main__.py`` script, prepend ``run_filename`` to ``sys.path``.
* If ``isolated`` is zero:
* If ``run_module`` is set, prepend the current directory to
``sys.path``. Do nothing if the current directory cannot be read.
* If ``run_filename`` is set, prepends the directory of the filename
to ``sys.path``.
* Otherwise, prepends an empty string to ``sys.path``.
If ``site_import`` is non-zero, ``sys.path`` can be modified by the
``site`` module. For example, if ``user_site_directory`` is non-zero,
the user site directory is added to ``sys.path`` (if it exists).
``site`` module. If ``user_site_directory`` is non-zero the user's
site-package directory exists, the ``site`` module appends the user's
site-package directory to ``sys.path``.
See also `Configuration Files`_ used by the path configuration.
@ -748,6 +795,94 @@ See `Python Configuration`_ for an example of customized Python always
running in isolated mode using ``Py_RunMain()``.
Multi-Phase Initialization Private Provisional API
--------------------------------------------------
This section is a private provisional API introducing multi-phase
initialization, the core feature of the PEP 432:
* "Core" initialization phase, "bare minimum Python":
* Builtin types;
* Builtin exceptions;
* Builtin and frozen modules;
* The ``sys`` module is only partially initialized
(ex: ``sys.path`` doesn't exist yet);
* "Main" initialization phase, Python is fully initialized:
* Install and configure ``importlib``;
* Apply the `Path Configuration`_;
* Install signal handlers;
* Finish ``sys`` module initialization (ex: create ``sys.stdout`` and
``sys.path``);
* Enable optional features like ``faulthandler`` and ``tracemalloc``;
* Import the ``site`` module;
* etc.
Private provisional API:
* ``PyConfig._init_main``: if set to 0, ``Py_InitializeFromConfig()``
stops at the "Core" initialization phase.
* ``PyStatus _Py_InitializeMain(void)``: move to the "Main"
initialization phase, finish the Python initialization.
No module is imported during the "Core" phase and the ``importlib``
module is not configured: the `Path Configuration`_ is only applied
during the "Main" phase. It allows to customize Python in Python to
override or tune the `Path Configuration`_, maybe install a custom
sys.meta_path importer or an import hook, etc.
It may become possible to compute the `Path Configuration`_ in Python,
after the Core phase and before the Main phase, which is one of the PEP
432 motivation.
The "Core" phase is not properly defined: what should be and what should
not be available at this phase is not specified yet. The API is marked
as private and provisional: the API can be modified or even be removed
anytime until a proper public API is design.
Example running Python code between "Core" and "Main" initialization
phases::
void init_python(void)
{
PyStatus status;
PyConfig config;
status = PyConfig_InitPythonConfig(&config);
if (PyStatus_Exception(status)) {
PyConfig_Clear(&config);
Py_ExitStatusException(status);
}
/* ... set 'config' configuration ... */
status = Py_InitializeFromConfig(&config);
PyConfig_Clear(&config);
if (PyStatus_Exception(status)) {
Py_ExitStatusException(status);
}
/* Use sys.stderr because sys.stdout is only created
by _Py_InitializeMain() */
int res = PyRun_SimpleString(
"import sys; "
"print('Run Python code before _Py_InitializeMain', "
"file=sys.stderr)");
if (res < 0) {
exit(1);
}
/* ... put more configuration code here ... */
status = _Py_InitializeMain();
if (PyStatus_Exception(status)) {
Py_ExitStatusException(status);
}
}
Backwards Compatibility
=======================
@ -776,9 +911,9 @@ PyPreConfig Python Isolated
``coerce_c_locale`` -1 0
``configure_locale`` **1** 0
``dev_mode`` -1 0
``isolated`` -1 **1**
``isolated`` 0 **1**
``legacy_windows_fs_encoding`` -1 0
``use_environment`` -1 0
``use_environment`` 0 0
``parse_argv`` **1** 0
``utf8_mode`` -1 0
=============================== ======= ========
@ -1025,9 +1160,9 @@ Default Python Configugration
* ``coerce_c_locale`` = -1
* ``configure_locale`` = 1
* ``dev_mode`` = -1
* ``isolated`` = -1
* ``isolated`` = 0
* ``legacy_windows_fs_encoding`` = -1
* ``use_environment`` = -1
* ``use_environment`` = 1
* ``utf8_mode`` = -1
``PyConfig_InitPythonConfig()``:
@ -1300,9 +1435,54 @@ Issues related to this PEP:
standalone) to locate the module path according to the shared library"
Discussions
===========
* May 2019:
* `[Python-Dev] PEP 587 "Python Initialization Configuration" version 4
<https://mail.python.org/pipermail/python-dev/2019-May/157492.html>`_
* `[Python-Dev] RFC: PEP 587 "Python Initialization Configuration": 3rd version
<https://mail.python.org/pipermail/python-dev/2019-May/157435.html>`_
* `Study on applications embedding Python
<https://mail.python.org/pipermail/python-dev/2019-May/157385.html>`_
* `[Python-Dev] RFC: PEP 587 "Python Initialization Configuration":
2nd version
<https://mail.python.org/pipermail/python-dev/2019-May/157290.html>`_
* March 2019:
* `[Python-Dev] PEP 587: Python Initialization Configuration
<https://mail.python.org/pipermail/python-dev/2019-March/156892.html>`_
* `[Python-Dev] New Python Initialization API
<https://mail.python.org/pipermail/python-dev/2019-March/156884.html>`_
* February 2019:
* `Adding char* based APIs for Unix
<https://discuss.python.org/t/adding-char-based-apis-for-unix/916>`_
* July-August 2018:
* July: `[Python-Dev] New _Py_InitializeFromConfig() function (PEP 432)
<https://mail.python.org/pipermail/python-dev/2018-July/154882.html>`__
* August: `[Python-Dev] New _Py_InitializeFromConfig() function (PEP 432)
<https://mail.python.org/pipermail/python-dev/2018-August/154896.html>`__
Version History
===============
* Version 5:
* Rename ``PyInitError`` to ``PyStatus``
* Rename ``PyInitError_Failed()`` to ``PyStatus_Exception()``
* Rename ``Py_ExitInitError()`` to ``Py_ExitStatusException()``
* Add ``PyPreConfig._config_init`` private field.
* Fix Python Configuration default values: isolated=0
and use_environment=1, instead of -1.
* Add "Multi-Phase Initialization Private Provisional API"
and "Discussions" sections
* Version 4:
* Introduce "Python Configuration" and "Isolated Configuration" which