mirror of
https://github.com/python/cpython.git
synced 2025-08-23 18:24:46 +00:00
gh-129033: Remove _Py_InitializeMain() function (#129034)
Co-authored-by: Alyssa Coghlan <ncoghlan@gmail.com>
This commit is contained in:
parent
c463270c73
commit
07c3518ffb
7 changed files with 15 additions and 153 deletions
|
@ -1946,89 +1946,13 @@ Py_GetArgcArgv()
|
||||||
|
|
||||||
See also :c:member:`PyConfig.orig_argv` member.
|
See also :c:member:`PyConfig.orig_argv` member.
|
||||||
|
|
||||||
|
Delaying main module execution
|
||||||
|
==============================
|
||||||
|
|
||||||
Multi-Phase Initialization Private Provisional API
|
In some embedding use cases, it may be desirable to separate interpreter initialization
|
||||||
==================================================
|
from the execution of the main module.
|
||||||
|
|
||||||
This section is a private provisional API introducing multi-phase
|
This separation can be achieved by setting ``PyConfig.run_command`` to the empty
|
||||||
initialization, the core feature of :pep:`432`:
|
string during initialization (to prevent the interpreter from dropping into the
|
||||||
|
interactive prompt), and then subsequently executing the desired main module
|
||||||
* "Core" initialization phase, "bare minimum Python":
|
code using ``__main__.__dict__`` as the global namespace.
|
||||||
|
|
||||||
* Builtin types;
|
|
||||||
* Builtin exceptions;
|
|
||||||
* Builtin and frozen modules;
|
|
||||||
* The :mod:`sys` module is only partially initialized
|
|
||||||
(ex: :data:`sys.path` doesn't exist yet).
|
|
||||||
|
|
||||||
* "Main" initialization phase, Python is fully initialized:
|
|
||||||
|
|
||||||
* Install and configure :mod:`importlib`;
|
|
||||||
* Apply the :ref:`Path Configuration <init-path-config>`;
|
|
||||||
* Install signal handlers;
|
|
||||||
* Finish :mod:`sys` module initialization (ex: create :data:`sys.stdout`
|
|
||||||
and :data:`sys.path`);
|
|
||||||
* Enable optional features like :mod:`faulthandler` and :mod:`tracemalloc`;
|
|
||||||
* Import the :mod:`site` module;
|
|
||||||
* etc.
|
|
||||||
|
|
||||||
Private provisional API:
|
|
||||||
|
|
||||||
* :c:member:`PyConfig._init_main`: if set to ``0``,
|
|
||||||
:c:func:`Py_InitializeFromConfig` stops at the "Core" initialization phase.
|
|
||||||
|
|
||||||
.. c:function:: 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 :ref:`Path Configuration <init-path-config>` is only
|
|
||||||
applied during the "Main" phase. It may allow to customize Python in Python to
|
|
||||||
override or tune the :ref:`Path Configuration <init-path-config>`, maybe
|
|
||||||
install a custom :data:`sys.meta_path` importer or an import hook, etc.
|
|
||||||
|
|
||||||
It may become possible to calculate the :ref:`Path Configuration
|
|
||||||
<init-path-config>` 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 designed.
|
|
||||||
|
|
||||||
Example running Python code between "Core" and "Main" initialization
|
|
||||||
phases::
|
|
||||||
|
|
||||||
void init_python(void)
|
|
||||||
{
|
|
||||||
PyStatus status;
|
|
||||||
|
|
||||||
PyConfig config;
|
|
||||||
PyConfig_InitPythonConfig(&config);
|
|
||||||
config._init_main = 0;
|
|
||||||
|
|
||||||
/* ... customize '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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1375,3 +1375,7 @@ Removed
|
||||||
|
|
||||||
* Creating :c:data:`immutable types <Py_TPFLAGS_IMMUTABLETYPE>` with mutable
|
* Creating :c:data:`immutable types <Py_TPFLAGS_IMMUTABLETYPE>` with mutable
|
||||||
bases was deprecated since 3.12 and now raises a :exc:`TypeError`.
|
bases was deprecated since 3.12 and now raises a :exc:`TypeError`.
|
||||||
|
|
||||||
|
* Remove the private ``_Py_InitializeMain()`` function. It was a
|
||||||
|
:term:`provisional API` added to Python 3.8 by :pep:`587`.
|
||||||
|
(Contributed by Victor Stinner in :gh:`129033`.)
|
||||||
|
|
|
@ -25,9 +25,6 @@ PyAPI_FUNC(PyStatus) Py_PreInitializeFromArgs(
|
||||||
PyAPI_FUNC(PyStatus) Py_InitializeFromConfig(
|
PyAPI_FUNC(PyStatus) Py_InitializeFromConfig(
|
||||||
const PyConfig *config);
|
const PyConfig *config);
|
||||||
|
|
||||||
// Python 3.8 provisional API (PEP 587)
|
|
||||||
PyAPI_FUNC(PyStatus) _Py_InitializeMain(void);
|
|
||||||
|
|
||||||
PyAPI_FUNC(int) Py_RunMain(void);
|
PyAPI_FUNC(int) Py_RunMain(void);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1274,24 +1274,6 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
}
|
}
|
||||||
self.check_all_configs("test_init_run_main", config, api=API_PYTHON)
|
self.check_all_configs("test_init_run_main", config, api=API_PYTHON)
|
||||||
|
|
||||||
def test_init_main(self):
|
|
||||||
code = ('import _testinternalcapi, json; '
|
|
||||||
'print(json.dumps(_testinternalcapi.get_configs()))')
|
|
||||||
config = {
|
|
||||||
'argv': ['-c', 'arg2'],
|
|
||||||
'orig_argv': ['python3',
|
|
||||||
'-c', code,
|
|
||||||
'arg2'],
|
|
||||||
'program_name': './python3',
|
|
||||||
'run_command': code + '\n',
|
|
||||||
'parse_argv': True,
|
|
||||||
'_init_main': False,
|
|
||||||
'sys_path_0': '',
|
|
||||||
}
|
|
||||||
self.check_all_configs("test_init_main", config,
|
|
||||||
api=API_PYTHON,
|
|
||||||
stderr="Run Python code before _Py_InitializeMain")
|
|
||||||
|
|
||||||
def test_init_parse_argv(self):
|
def test_init_parse_argv(self):
|
||||||
config = {
|
config = {
|
||||||
'parse_argv': True,
|
'parse_argv': True,
|
||||||
|
@ -1768,7 +1750,6 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
|
|
||||||
def test_init_set_config(self):
|
def test_init_set_config(self):
|
||||||
config = {
|
config = {
|
||||||
'_init_main': 0,
|
|
||||||
'bytes_warning': 2,
|
'bytes_warning': 2,
|
||||||
'warnoptions': ['error::BytesWarning'],
|
'warnoptions': ['error::BytesWarning'],
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Remove the private ``_Py_InitializeMain()`` function. It was a
|
||||||
|
:term:`provisional API` added to Python 3.8 by :pep:`587`. Patch by Victor
|
||||||
|
Stinner.
|
|
@ -1818,7 +1818,6 @@ static int test_init_set_config(void)
|
||||||
PyConfig config;
|
PyConfig config;
|
||||||
PyConfig_InitIsolatedConfig(&config);
|
PyConfig_InitIsolatedConfig(&config);
|
||||||
config_set_string(&config, &config.program_name, PROGRAM_NAME);
|
config_set_string(&config, &config.program_name, PROGRAM_NAME);
|
||||||
config._init_main = 0;
|
|
||||||
config.bytes_warning = 0;
|
config.bytes_warning = 0;
|
||||||
init_from_config_clear(&config);
|
init_from_config_clear(&config);
|
||||||
|
|
||||||
|
@ -1828,12 +1827,6 @@ static int test_init_set_config(void)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finish initialization: main part
|
|
||||||
PyStatus status = _Py_InitializeMain();
|
|
||||||
if (PyStatus_Exception(status)) {
|
|
||||||
Py_ExitStatusException(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
dump_config();
|
dump_config();
|
||||||
Py_Finalize();
|
Py_Finalize();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2089,33 +2082,6 @@ static int test_init_run_main(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int test_init_main(void)
|
|
||||||
{
|
|
||||||
PyConfig config;
|
|
||||||
PyConfig_InitPythonConfig(&config);
|
|
||||||
|
|
||||||
configure_init_main(&config);
|
|
||||||
config._init_main = 0;
|
|
||||||
init_from_config_clear(&config);
|
|
||||||
|
|
||||||
/* sys.stdout don't exist yet: it is 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyStatus status = _Py_InitializeMain();
|
|
||||||
if (PyStatus_Exception(status)) {
|
|
||||||
Py_ExitStatusException(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Py_RunMain();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int test_run_main(void)
|
static int test_run_main(void)
|
||||||
{
|
{
|
||||||
PyConfig config;
|
PyConfig config;
|
||||||
|
@ -2473,7 +2439,6 @@ static struct TestCase TestCases[] = {
|
||||||
{"test_preinit_dont_parse_argv", test_preinit_dont_parse_argv},
|
{"test_preinit_dont_parse_argv", test_preinit_dont_parse_argv},
|
||||||
{"test_init_read_set", test_init_read_set},
|
{"test_init_read_set", test_init_read_set},
|
||||||
{"test_init_run_main", test_init_run_main},
|
{"test_init_run_main", test_init_run_main},
|
||||||
{"test_init_main", test_init_main},
|
|
||||||
{"test_init_sys_add", test_init_sys_add},
|
{"test_init_sys_add", test_init_sys_add},
|
||||||
{"test_init_setpath", test_init_setpath},
|
{"test_init_setpath", test_init_setpath},
|
||||||
{"test_init_setpath_config", test_init_setpath_config},
|
{"test_init_setpath_config", test_init_setpath_config},
|
||||||
|
|
|
@ -1505,18 +1505,6 @@ Py_Initialize(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PyStatus
|
|
||||||
_Py_InitializeMain(void)
|
|
||||||
{
|
|
||||||
PyStatus status = _PyRuntime_Initialize();
|
|
||||||
if (_PyStatus_EXCEPTION(status)) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
PyThreadState *tstate = _PyThreadState_GET();
|
|
||||||
return pyinit_main(tstate);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
finalize_modules_delete_special(PyThreadState *tstate, int verbose)
|
finalize_modules_delete_special(PyThreadState *tstate, int verbose)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue