@@ -2299,13 +2299,89 @@ Py_GetArgcArgv()
22992299
23002300 See also :c:member: `PyConfig.orig_argv ` member.
23012301
2302- Delaying main module execution
2303- ==============================
23042302
2305- In some embedding use cases, it may be desirable to separate interpreter initialization
2306- from the execution of the main module.
2303+ Multi-Phase Initialization Private Provisional API
2304+ ==================================================
23072305
2308- This separation can be achieved by setting ``PyConfig.run_command `` to the empty
2309- string during initialization (to prevent the interpreter from dropping into the
2310- interactive prompt), and then subsequently executing the desired main module
2311- code using ``__main__.__dict__`` as the global namespace.
2306+ This section is a private provisional API introducing multi-phase
2307+ initialization, the core feature of :pep: `432 `:
2308+
2309+ * "Core" initialization phase, "bare minimum Python":
2310+
2311+ * Builtin types;
2312+ * Builtin exceptions;
2313+ * Builtin and frozen modules;
2314+ * The :mod: `sys ` module is only partially initialized
2315+ (ex: :data: `sys.path ` doesn't exist yet).
2316+
2317+ * "Main" initialization phase, Python is fully initialized:
2318+
2319+ * Install and configure :mod:`importlib`;
2320+ * Apply the :ref: `Path Configuration <init-path-config >`;
2321+ * Install signal handlers;
2322+ * Finish :mod: `sys ` module initialization (ex: create :data: `sys.stdout `
2323+ and :data: `sys.path `);
2324+ * Enable optional features like :mod: `faulthandler ` and :mod: `tracemalloc `;
2325+ * Import the :mod: `site ` module;
2326+ * etc.
2327+
2328+ Private provisional API:
2329+
2330+ * :c:member: `PyConfig._init_main `: if set to ``0 ``,
2331+ :c:func: `Py_InitializeFromConfig ` stops at the "Core" initialization phase.
2332+
2333+ .. c :function :: PyStatus _Py_InitializeMain (void)
2334+
2335+ Move to the "Main" initialization phase, finish the Python initialization.
2336+
2337+ No module is imported during the "Core" phase and the ``importlib`` module is
2338+ not configured: the :ref:`Path Configuration <init-path-config>` is only
2339+ applied during the "Main" phase. It may allow to customize Python in Python to
2340+ override or tune the :ref:`Path Configuration <init-path-config>`, maybe
2341+ install a custom :data:`sys.meta_path` importer or an import hook, etc.
2342+
2343+ It may become possible to calculate the :ref:`Path Configuration
2344+ <init-path-config>` in Python, after the Core phase and before the Main phase,
2345+ which is one of the :pep:`432` motivation.
2346+
2347+ The "Core" phase is not properly defined: what should be and what should
2348+ not be available at this phase is not specified yet. The API is marked
2349+ as private and provisional: the API can be modified or even be removed
2350+ anytime until a proper public API is designed.
2351+
2352+ Example running Python code between "Core" and "Main" initialization
2353+ phases::
2354+
2355+ void init_python(void)
2356+ {
2357+ PyStatus status;
2358+
2359+ PyConfig config;
2360+ PyConfig_InitPythonConfig (&config);
2361+ config._init_main = 0;
2362+
2363+ /* ... customize 'config' configuration ... */
2364+
2365+ status = Py_InitializeFromConfig (&config);
2366+ PyConfig_Clear (&config);
2367+ if (PyStatus_Exception (status)) {
2368+ Py_ExitStatusException (status);
2369+ }
2370+
2371+ /* Use sys.stderr because sys.stdout is only created
2372+ by _Py_InitializeMain () */
2373+ int res = PyRun_SimpleString(
2374+ "import sys; "
2375+ "print('Run Python code before _Py_InitializeMain', "
2376+ "file=sys.stderr)");
2377+ if (res < 0) {
2378+ exit(1);
2379+ }
2380+
2381+ /* ... put more configuration code here ... */
2382+
2383+ status = _Py_InitializeMain ();
2384+ if (PyStatus_Exception (status)) {
2385+ Py_ExitStatusException (status);
2386+ }
2387+ }
0 commit comments