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:
parent
74f0fb256d
commit
fcdd72d719
388
pep-0587.rst
388
pep-0587.rst
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue