PEP 432: update to target 3.7/3.8

- timeline updates based on completely missing the 3.6/3.7 targets
- API design & implementation strategy updates based on recent
  discussions with Eric Snow, Steve Dower & Brett Cannon
This commit is contained in:
Nick Coghlan 2016-12-31 17:07:04 +10:00
parent 361599ec4b
commit 9f3a93dc85
1 changed files with 148 additions and 145 deletions

View File

@ -1,5 +1,5 @@
PEP: 432
Title: Simplifying the CPython startup sequence
Title: Restructuring the CPython startup sequence
Version: $Revision$
Last-Modified: $Date$
Author: Nick Coghlan <ncoghlan@gmail.com>
@ -7,19 +7,28 @@ Status: Draft
Type: Standards Track
Content-Type: text/x-rst
Created: 28-Dec-2012
Python-Version: 3.6
Python-Version: 3.8
Post-History: 28-Dec-2012, 2-Jan-2013
Abstract
========
This PEP proposes a mechanism for simplifying the startup sequence for
This PEP proposes a mechanism for restructuring the startup sequence for
CPython, making it easier to modify the initialization behaviour of the
reference interpreter executable, as well as making it easier to control
CPython's startup behaviour when creating an alternate executable or
embedding it as a Python execution engine inside a larger application.
When implementation of this proposal is completed, interpreter startup will
consist of two clearly distinct and independently configurable phases:
* Python runtime initialization
* Main interpreter configuration
Changes are also proposed that impact main module execution and subinterpreter
initialization.
Note: TBC = To Be Confirmed, TBD = To Be Determined. The appropriate
resolution for most of these should become clearer as the reference
implementation is developed.
@ -32,7 +41,7 @@ This PEP proposes that initialization of the CPython runtime be split into
two clearly distinct phases:
* core runtime initialization
* main interpreter initialization
* main interpreter configuration
The proposed design also has significant implications for:
@ -43,7 +52,7 @@ In the new design, the interpreter will move through the following
well-defined phases during the initialization sequence:
* Pre-Initialization - no interpreter available
* Core Initialized - main interpreter partially available,
* Runtime Initialized - main interpreter partially available,
subinterpreter creation not yet available
* Initialized - main interpreter fully available, subinterpreter creation
available
@ -94,9 +103,9 @@ in a cross-platform fashion [7_], controlling the configuration of
tracing when launching Python subprocesses [9_]).
Rather than continuing to bolt such behaviour onto an already complicated
system, this PEP proposes to start simplifying the status quo by introducing
a more structured startup sequence, with the aim of making these further
feature requests easier to implement.
system indefinitely, this PEP proposes to start simplifying the status quo by
introducing a more structured startup sequence, with the aim of making these
further feature requests easier to implement.
Key Concerns
@ -116,9 +125,9 @@ as lists, dictionaries and Unicode values being created prior to the call
to ``Py_Initialize`` when the ``-X`` or ``-W`` options are used [1_].
By moving to an explicitly multi-phase startup sequence, developers should
only need to understand which features are not available in the core
bootstrapping phase, as the vast majority of the configuration process
will now take place during that phase.
only need to understand which features are not available in the main
interpreter configuration phase, as the vast majority of the configuration
process will now take place during that phase.
By basing the new design on a combination of C structures and Python
data types, it should also be easier to modify the system in the
@ -150,12 +159,12 @@ tear down the interpreter::
python3 -m timeit -s "from subprocess import call" "call(['./python', '-c', 'pass'])"
Current numbers on my system for Python 3.6 (using the 3.5
Current numbers on my system for Python 3.7 (using the 3.5
subprocess and timeit modules to execute the check, all with non-debug
builds)::
$ python3 -m timeit -s "from subprocess import call" "call(['./python', '-c', 'pass'])"
100 loops, best of 3: 15.1 msec per loop
100 loops, best of 3: 13.9 msec per loop
This PEP is not expected to have any significant effect on the startup time,
as it is aimed primarily at *reordering* the existing initialization
@ -247,7 +256,7 @@ be able to control the following aspects of the final interpreter state:
* Standard input as a script (i.e. a non-interactive stream)
* Standard input as an interactive interpreter session
<TBD: Did I miss anything?>
<TBD: What, if anything, is still missing from this list?>
Note that this just covers settings that are currently configurable in some
manner when using the main CPython executable. While this PEP aims to make
@ -270,18 +279,18 @@ structure a draft implementation that won't be prone to the kinds of merge
conflicts that afflicted the original attempt.
Accordingly, the implementation strategy now being proposed is to implement this
refactoring as a private API for CPython 3.6, before exposing the new functions
and structures as public API elements in CPython 3.7.
refactoring as a private API for CPython 3.7, before exposing the new functions
and structures as public API elements in CPython 3.8.
The affected APIs with a leading underscore, as they would be named in CPython
3.6:
3.7:
* ``_Py_IsCoreInitialized``
* ``_Py_InitializeCore``
* ``_PyCoreConfig``
* ``_PyCoreConfig_INIT``
* ``_Py_IsRuntimeInitialized``
* ``_Py_InitializeRuntime``
* ``_PyRuntimeConfig``
* ``_PyRuntimeConfig_INIT``
* ``_Py_ReadHashSeed``
* ``_Py_InitializeMainInterpreter``
* ``_Py_ConfigureMainInterpreter``
* ``_PyMainInterpreterConfig``
* ``_PyInterpreterConfig``
* ``_Py_ReadMainInterpreterConfig``
@ -294,15 +303,15 @@ intended to be retained permanently as private CPython implementation details.
The principle benefit of this approach is allowing the refactoring to adopt the
new configuration structures to be handled on a setting by setting basis
over the course of the 3.6 and 3.7 development cycles, rather than having to
migrate them in a single monolithic change. It also means any new settings can
be handled using the new approach, even if some existing settings have yet to
be migrated.
over the course of the 3.7 and 3.8 development cycles, rather than having to
migrate them in a single monolithic change. It also means any new settings
introduced for these releases can be handled using the new approach from the
start, even if some existing settings have yet to be migrated.
If all existing settings are successfully migrated to the new initialization
model in time for the 3.6.0a4 release in August 2016, then the proposal would
be to make the APIs public for the 3.6.0b1 release in September 2016, rather
than waiting for 3.7.
model in time for the 3.7.0a4 release in December 2017, then the proposal would
be to make the APIs public for the 3.7.0b1 release in January 2018, rather
than waiting for 3.8.
Design Details
@ -311,12 +320,13 @@ Design Details
(Note: details here are still very much in flux, but preliminary feedback
is appreciated anyway)
The main theme of this proposal is to create the interpreter state for
the main interpreter *much* earlier in the startup process. This will allow
most of the CPython API to be used during the remainder of the initialization
process, potentially simplifying a number of operations that currently need
to rely on basic C functionality rather than being able to use the richer
data structures provided by the CPython C API.
The main theme of this proposal is to initialize the core language runtime
and create a partially initialized interpreter state for the main interpreter
*much* earlier in the startup process. This will allow most of the CPython API
to be used during the remainder of the initialization process, potentially
simplifying a number of operations that currently need to rely on basic C
functionality rather than being able to use the richer data structures provided
by the CPython C API.
In the following, the term "embedding application" also covers the standard
CPython command line application.
@ -329,29 +339,31 @@ Three distinct interpreter initialisation phases are proposed:
* Pre-Initialization:
* no interpreter is available.
* ``Py_IsCoreInitialized()`` returns ``0``
* no interpreter is available
* ``Py_IsRuntimeInitialized()`` returns ``0``
* ``Py_IsInitialized()`` returns ``0``
* The embedding application determines the settings required to create the
main interpreter and moves to the next phase by calling
``Py_InitializeCore``.
* The embedding application determines the settings required to initialize
the core CPython runtime and create the main interpreter and moves to the
next phase by calling ``Py_InitializeRuntime``
* Core Initialized:
* Initializing:
* the main interpreter is available, but only partially configured.
* ``Py_IsCoreInitialized()`` returns ``1``
* the builtin data types and other core runtime services are available
* the main interpreter is available, but only partially configured
* ``Py_IsRuntimeInitialized()`` returns ``1``
* ``Py_IsInitialized()`` returns ``0``
* The embedding application determines and applies the settings
required to complete the initialization process by calling
``Py_ReadMainInterpreterConfig`` and ``Py_InitializeMainInterpreter``.
``Py_ReadMainInterpreterConfig`` and ``Py_ConfigureMainInterpreter``.
* Initialized:
* the main interpreter is available and fully operational, but
``__main__`` related metadata is incomplete
* ``Py_IsCoreInitialized()`` returns ``1``
* ``Py_IsRuntimeInitialized()`` returns ``1``
* ``Py_IsInitialized()`` returns ``1``
Invocation of Phases
--------------------
@ -366,18 +378,18 @@ grained API, which allows the embedding application greater control
over the initialization process::
/* Phase 1: Pre-Initialization */
PyCoreConfig core_config = PyCoreConfig_INIT;
PyMainInterpreterConfig config;
PyRuntimeConfig runtime_config = PyRuntimeConfig_INIT;
PyMainInterpreterConfig interpreter_config;
/* Easily control the core configuration */
core_config.ignore_environment = 1; /* Ignore environment variables */
core_config.use_hash_seed = 0; /* Full hash randomisation */
Py_InitializeCore(&core_config);
/* Phase 2: Initialization */
runtime_config.ignore_environment = 1; /* Ignore environment variables */
runtime_config.use_hash_seed = 0; /* Full hash randomisation */
Py_InitializeRuntime(&runtime_config);
/* Phase 2: Initializing */
/* Optionally preconfigure some settings here - they will then be
* used to derive other settings */
Py_ReadMainInterpreterConfig(&config);
Py_ReadMainInterpreterConfig(&interpreter_config);
/* Can completely override derived settings here */
Py_InitializeMainInterpreter(&config);
Py_ConfigureMainInterpreter(&interpreter_config);
/* Phase 3: Initialized */
/* If an embedding application has no real concept of a main module
* it can just stop the initialization process here.
@ -389,7 +401,7 @@ Pre-Initialization Phase
------------------------
The pre-initialization phase is where an embedding application determines
the settings which are absolutely required before the interpreter can be
the settings which are absolutely required before the CPython runtime can be
initialized at all. Currently, the primary configuration settings in this
category are those related to the randomised hash algorithm - the hash
algorithms must be consistent for the lifetime of the process, and so they
@ -406,7 +418,7 @@ system.
The proposed API for this step in the startup sequence is::
void Py_InitializeCore(const PyCoreConfig *config);
void Py_InitializeRuntime(const PyRuntimeConfig *config);
Like ``Py_Initialize``, this part of the new API treats initialization failures
as fatal errors. While that's still not particularly embedding friendly,
@ -414,34 +426,31 @@ the operations in this step *really* shouldn't be failing, and changing them
to return error codes instead of aborting would be an even larger task than
the one already being proposed.
The new ``PyCoreConfig`` struct holds the settings required for preliminary
The new ``PyRuntimeConfig`` struct holds the settings required for preliminary
configuration of the core runtime and creation of the main interpreter::
/* Note: if changing anything in PyCoreConfig, also update
* PyCoreConfig_INIT */
/* Note: if changing anything in PyRuntimeConfig, also update
* PyRuntimeConfig_INIT */
typedef struct {
int ignore_environment; /* -E switch, -I switch */
bool ignore_environment; /* -E switch, -I switch */
int use_hash_seed; /* PYTHONHASHSEED */
unsigned long hash_seed; /* PYTHONHASHSEED */
int _disable_importlib; /* Needed by freeze_importlib */
} PyCoreConfig;
bool _disable_importlib; /* Needed by freeze_importlib */
} PyRuntimeConfig;
#define PyCoreConfig_INIT {.use_hash_seed=-1}
/* The above assumes PEP 7 is updated to permit use of C99 features
* Without designated initialisers, the macro would be:
* #define PyCoreConfig_INIT {0, -1, 0, 0}
*/
/* Rely on the "designated initializer" feature of C99 */
#define PyRuntimeConfig_INIT {.use_hash_seed=-1}
The core configuration settings pointer may be ``NULL``, in which case the
default values are ``ignore_environment = -1`` and ``use_hash_seed = -1``.
default values are as specified in ``PyRuntimeConfig_INIT``.
The ``PyCoreConfig_INIT`` macro is designed to allow easy initialization
The ``PyRuntimeConfig_INIT`` macro is designed to allow easy initialization
of a struct instance with sensible defaults::
PyCoreConfig core_config = PyCoreConfig_INIT;
PyRuntimeConfig runtime_config = PyRuntimeConfig_INIT;
``ignore_environment`` controls the processing of all Python related
environment variables. If the flag is zero, then environment variables are
environment variables. If the flag is false, then environment variables are
processed normally. Otherwise, all Python-specific environment variables
are considered undefined (exceptions may be made for some OS specific
environment variables, such as those used on Mac OS X to communicate
@ -480,30 +489,32 @@ value indicates an error (most likely in the conversion to an integer).
The ``_disable_importlib`` setting is used as part of the CPython build
process to create an interpreter with no import capability at all. It is
considered private to the CPython development team (hence the leading
underscore), as the only known use case is to permit compiler changes
that invalidate the previously frozen bytecode for ``importlib._bootstrap``
without breaking the build process.
underscore), as the only currently supported use case is to permit compiler
changes that invalidate the previously frozen bytecode for
``importlib._bootstrap`` without breaking the build process.
The aim is to keep this initial level of configuration as small as possible
in order to keep the bootstrapping environment consistent across
different embedding applications. If we can create a valid interpreter state
without the setting, then the setting should go in the configuration passed
to ``Py_InitializeMainInterpreter()`` rather than in the core configuration.
to ``Py_ConfigureMainInterpreter()`` rather than in the core runtime
configuration.
A new query API will allow code to determine if the interpreter is in the
bootstrapping state between the creation of the interpreter state and the
completion of the bulk of the initialization process::
bootstrapping state between the core runtime initialization and the creation of
the main interpreter state and the completion of the bulk of the main
interpreter initialization process::
int Py_IsCoreInitialized();
int Py_IsRuntimeInitialized();
Attempting to call ``Py_InitializeCore()`` again when
``Py_IsCoreInitialized()`` is already true is a fatal error.
Attempting to call ``Py_InitializeRuntime()`` again when
``Py_IsRuntimeInitialized()`` is already true is a fatal error.
As frozen bytecode may now be legitimately run in an interpreter which is not
yet fully initialized, ``sys.flags`` will gain a new ``initialized`` flag.
With the core runtime initialised, the interpreter should be fully functional
except that:
With the core runtime initialised, the main interpreter and most of the CPython
C API should be fully functional except that:
* compilation is not allowed (as the parser and compiler are not yet
configured properly)
@ -542,12 +553,12 @@ to be used safely for all of the remaining configuration steps (unlike the
status quo).
In addition, the current thread will possess a valid Python thread state,
allowing any further configuration data to be stored on the interpreter
allowing any further configuration data to be stored on the main interpreter
object rather than in C process globals.
Any call to ``Py_InitializeCore()`` must have a matching call to
Any call to ``Py_InitializeRuntime()`` must have a matching call to
``Py_Finalize()``. It is acceptable to skip calling
``Py_InitializeMainInterpreter()`` in between (e.g. if attempting to read the
``Py_ConfigureMainInterpreter()`` in between (e.g. if attempting to read the
main interpreter configuration settings fails).
@ -562,8 +573,8 @@ interpreter state at this point. The core API for this step is::
The config argument should be a pointer to a config struct (which may be
a temporary one stored on the C stack). For any already configured value
(i.e. non-NULL pointer or non-negative numeric value), CPython will sanity
check the supplied value, but otherwise accept it as correct.
(i.e. any non-NULL pointer), CPython will sanity check the supplied value,
but otherwise accept it as correct.
A struct is used rather than a Python dictionary as the struct is easier
to work with from C, the list of supported fields is fixed for a given
@ -571,7 +582,7 @@ CPython version and only a read-only view needs to be exposed to Python
code (which is relatively straightforward, thanks to the infrastructure
already put in place to expose ``sys.implementation``).
Unlike ``Py_Initialize`` and ``Py_InitializeCore``, this call will raise
Unlike ``Py_Initialize`` and ``Py_InitializeRuntime``, this call will raise
an exception and report an error return rather than exhibiting fatal errors
if a problem is found with the config data.
@ -588,7 +599,7 @@ such as removing ``sys.path[0]``).
Merely reading the configuration has no effect on the interpreter state: it
only modifies the passed in configuration struct. The settings are not
applied to the running interpreter until the ``Py_InitializeMainInterpreter``
applied to the running interpreter until the ``Py_ConfigureMainInterpreter``
call (see below).
@ -610,8 +621,6 @@ complete the main interpreter configuration. These settings are also all
passed through unmodified to subinterpreters. Fields are always pointers to
Python data types, with unset values indicated by ``NULL``::
/* Note: if changing anything in PyMainInterpreterConfig, also update
* PyMainInterpreterConfig_INIT */
typedef struct {
/* Argument processing */
PyListObject *raw_argv;
@ -686,20 +695,20 @@ Python data types, with unset values indicated by ``NULL``::
} PyMainInterpreterConfig;
/* Storing all state as Python object pointers */
The ``PyInterpreterConfig`` struct holds the settings that may vary between
the main interpreter and subinterpreters. For the main interpreter, these
settings are automatically populated by ``Py_InitializeMainInterpreter()``.
settings are automatically populated by ``Py_ConfigureMainInterpreter()``.
::
/* Note: if changing anything in PyInterpreterConfig, also update
* PyInterpreterConfig_INIT */
typedef struct {
PyBoolObject *is_main_interpreter; /* Easily check for subinterpreters */
} PyInterpreterConfig;
As these structs consist solely of object pointers, no explicit initializer
definitions are needed - C99's default initialization of struct memory to zero
is sufficient.
<TBD: did I miss anything?>
@ -710,7 +719,7 @@ The final step in the initialization process is to actually put the
configuration settings into effect and finish bootstrapping the main
interpreter up to full operation::
int Py_InitializeMainInterpreter(const PyMainInterpreterConfig *config);
int Py_ConfigureMainInterpreter(const PyMainInterpreterConfig *config);
Like ``Py_ReadMainInterpreterConfig``, this call will raise an exception and
report an error return rather than exhibiting fatal errors if a problem is
@ -724,7 +733,7 @@ After a successful call ``Py_IsInitialized()`` will become true. The caveats
described above for the interpreter during the phase where only the core
runtime is initialized will no longer hold.
Attempting to call ``Py_InitializeMainInterpreter()`` again when
Attempting to call ``Py_ConfigureMainInterpreter()`` again when
``Py_IsInitialized()`` is true is an error.
However, some metadata related to the ``__main__`` module may still be
@ -746,10 +755,10 @@ incomplete:
builtin module
This function will normally implicitly import site as its final operation
(after ``Py_IsInitialized()`` is already set). Clearing the
"enable_site_config" flag in the configuration settings will disable this
behaviour, as well as eliminating any side effects on global state if
``import site`` is later explicitly executed in the process.
(after ``Py_IsInitialized()`` is already set). Setting the
"enable_site_config" flag to ``Py_False`` in the configuration settings will
disable this behaviour, as well as eliminating any side effects on global
state if ``import site`` is later explicitly executed in the process.
Preparing the main module
@ -840,16 +849,16 @@ If both ``main_stream`` and ``main_code`` are set, ``RuntimeError`` will
be reported.
If ``main_stream`` and ``prompt_stream`` are both set, main execution will
be delegated to a new API::
be delegated to a new internal API::
int _PyRun_InteractiveMain(PyObject *input, PyObject* output);
If ``main_stream`` is set and ``prompt_stream`` is NULL, main execution will
be delegated to a new API::
be delegated to a new internal API::
int _PyRun_StreamInMain(PyObject *input);
If ``main_code`` is set, main execution will be delegated to a new
If ``main_code`` is set, main execution will be delegated to a new internal
API::
int _PyRun_CodeInMain(PyCodeObject *code);
@ -865,17 +874,24 @@ Internal Storage of Configuration Data
The interpreter state will be updated to include details of the configuration
settings supplied during initialization by extending the interpreter state
object with an embedded copy of the ``PyCoreConfig``,
object with an embedded copy of the ``PyRuntimeConfig``,
``PyMainInterpreterConfig`` and ``PyInterpreterConfig`` structs.
For debugging purposes, the configuration settings will be exposed as
a ``sys._configuration`` simple namespace (similar to ``sys.flags`` and
``sys.implementation``. Field names will match those in the configuration
structs, except for ``hash_seed``, which will be deliberately excluded.
``sys.implementation``. The attributes will be themselves by simple namespaces
corresponding to the three levels of configurations setting:
* ``runtime``
* ``main_interpreter``
* ``interpreter``
Field names will match those in the configuration structs, except for
``hash_seed``, which will be deliberately excluded.
An underscored attribute is chosen deliberately, as these configuration
settings are part of the CPython implementation, rather than part of the
Python language definition. If settings are needed to support
Python language definition. If new settings are needed to support
cross-implementation compatibility in the standard library, then those
should be agreed with the other implementations and exposed as new required
attributes on ``sys.implementation``, as described in PEP 421.
@ -889,7 +905,7 @@ Creating and Configuring Subinterpreters
As the new configuration settings are stored in the interpreter state, they
need to be initialised when a new subinterpreter is created. This turns out
to be trickier than one might think due to ``PyThreadState_Swap(NULL);``
to be trickier than one might expect due to ``PyThreadState_Swap(NULL);``
(which is fortunately exercised by CPython's own embedding tests, allowing
this problem to be detected during development).
@ -898,7 +914,7 @@ add a new API::
Py_InterpreterState *Py_InterpreterState_Main();
This will be a counterpart to Py_InterpreterState_Head(), reporting the
This will be a counterpart to ``Py_InterpreterState_Head()``, only reporting the
oldest currently existing interpreter rather than the newest. If
``Py_NewInterpreter()`` is called from a thread with an existing thread
state, then the interpreter configuration for that thread will be
@ -909,7 +925,7 @@ will be used.
While the existing ``Py_InterpreterState_Head()`` API could be used instead,
that reference changes as subinterpreters are created and destroyed, while
``PyInterpreterState_Main()`` will always refer to the initial interpreter
state created in ``Py_InitializeCore()``.
state created in ``Py_InitializeRuntime()``.
A new constraint is also added to the embedding API: attempting to delete
the main interpreter while subinterpreters still exist will now be a fatal
@ -921,10 +937,10 @@ Stable ABI
Most of the APIs proposed in this PEP are excluded from the stable ABI, as
embedding a Python interpreter involves a much higher degree of coupling
than merely writing an extension.
than merely writing an extension module.
The only newly exposed API that will be part of the stable ABI is the
``Py_IsCoreInitialized()`` query.
``Py_IsRuntimeInitialized()`` query.
Build time configuration
@ -941,14 +957,14 @@ Backwards Compatibility
Backwards compatibility will be preserved primarily by ensuring that
``Py_ReadMainInterpreterConfig()`` interrogates all the previously defined
configuration settings stored in global variables and environment variables,
and that ``Py_InitializeMainInterpreter()`` writes affected settings back to
and that ``Py_ConfigureMainInterpreter()`` writes affected settings back to
the relevant locations.
One acknowledged incompatibility is that some environment variables which
are currently read lazily may instead be read once during interpreter
initialization. As the PEP matures, these will be discussed in more detail
on a case by case basis. The environment variables which are currently
known to be looked up dynamically are:
initialization. As the reference implementation matures, these will be
discussed in more detail on a case by case basis. The environment variables
which are currently known to be looked up dynamically are:
* ``PYTHONCASEOK``: writing to ``os.environ['PYTHONCASEOK']`` will no longer
dynamically alter the interpreter's handling of filename case differences
@ -960,10 +976,10 @@ The ``Py_Initialize()`` style of initialization will continue to be
supported. It will use (at least some elements of) the new API
internally, but will continue to exhibit the same behaviour as it
does today, ensuring that ``sys.argv`` is not populated until a subsequent
``PySys_SetArgv`` call. All APIs that currently support being called
``PySys_SetArgv`` call (TBC). All APIs that currently support being called
prior to ``Py_Initialize()`` will
continue to do so, and will also support being called prior to
``Py_InitializeCore()``.
``Py_InitializeRuntime()``.
To minimise unnecessary code churn, and to ensure the backwards compatibility
is well tested, the main CPython executable may continue to use some elements
@ -1012,43 +1028,30 @@ Open Questions
==============
* Error details for ``Py_ReadMainInterpreterConfig`` and
``Py_InitializeMainInterpreter`` (these should become clearer as the
``Py_ConfigureMainInterpreter`` (these should become clearer as the
implementation progresses)
* Is initialisation of the ``PyMainInterpreterConfig`` struct too unwieldy to
be maintainable? Would a Python dictionary be a better choice, despite
being harder to work with from C code? Can we upgrade to requiring a C99
compatible compiler?
* Would it be better to manage the flag variables in ``PyMainInterpreterConfig``
as Python integers or as "negative means false, positive means true, zero
means not set" so the struct can be initialized with a simple
``memset(&config, 0, sizeof(*config))``, eliminating the need to update
both PyMainInterpreterConfig and PyMainInterpreterConfig_INIT when adding
new fields?
* The name of the new system Python executable is a bikeshed waiting to be
painted. The 4 options considered so far are ``spython``, ``pysystem``,
``python-minimal`` and `system-python``. The PEP text reflects my current
preferred choice (``system-python``).
Implementation
==============
A reference implementation is available as a feature branch in my BitBucket
sandbox [2_].
A reference implementation is available as a feature branch in Nick Coghlan's
CPython sandbox on BitBucket [2_].
It implements the ``_Py_InitializeCore`` and ``_Py_InitializeMainInterpreter``
aspects of the refactoring as a private API. All ``_PyCoreConfig`` settings
It implements the ``_Py_InitializeRuntime`` and ``_Py_ConfigureMainInterpreter``
aspects of the refactoring as a private API. All ``_PyRuntimeConfig`` settings
are included, but currently only the "install signal handlers" setting is
implemented for the main interpreter configuration.
The currently available interfaces in the reference implementation:
The feature branch is a couple of iterations behind the API design in the PEP
so the exact interfaces currently available are:
* ``_Py_IsCoreInitialized``
* ``_Py_InitializeCore``
* ``_PyCoreConfig``
* ``_PyCoreConfig_INIT``
* ``_Py_IsCoreInitialized`` (rename pending: ``_Py_IsRuntimeInitialized``)
* ``_Py_InitializeCore`` (rename pending: ``_Py_InitializeRuntime``)
* ``_PyCoreConfig`` (rename pending: ``_Py_RuntimeConfig``)
* ``_PyCoreConfig_INIT`` (rename pending: ``_Py_RuntimeConfig_INIT``)
* ``_Py_ReadHashSeed``
* ``_Py_InitializeMainInterpreter``
* ``_Py_InitializeMainInterpreter`` (rename pending: ``_Py_ConfigureMainInterpreter``)
* ``_PyMainInterpreterConfig``
* ``_PyMainInterpreterConfig_INIT``
* ``_Py_ReadMainInterpreterConfig``
@ -1062,7 +1065,7 @@ a fairly ad hoc fashion over the past 20+ years, leading to a rather
inconsistent interface with varying levels of documentation.
(Note: some of the info below could probably be cleaned up and added to the
C API documentation for at least 3.3. - it's all CPython specific, so it
C API documentation for 3.6 - it's all CPython specific, so it
doesn't belong in the language reference)