mirror of
https://github.com/python/cpython.git
synced 2025-09-27 02:39:58 +00:00
bpo-34008: Allow to call Py_Main() after Py_Initialize() (GH-8043)
Py_Main() can again be called after Py_Initialize(), as in Python 3.6. The new configuration is ignored, except of _PyMainInterpreterConfig.argv which is used to update sys.argv.
This commit is contained in:
parent
2c5c0a367c
commit
fb47bca9ee
5 changed files with 52 additions and 6 deletions
|
@ -238,6 +238,14 @@ class EmbeddingTests(unittest.TestCase):
|
||||||
self.assertEqual(out, '')
|
self.assertEqual(out, '')
|
||||||
self.assertEqual(err, '')
|
self.assertEqual(err, '')
|
||||||
|
|
||||||
|
def test_initialize_pymain(self):
|
||||||
|
"""
|
||||||
|
bpo-34008: Calling Py_Main() after Py_Initialize() must not fail.
|
||||||
|
"""
|
||||||
|
out, err = self.run_embedded_interpreter("initialize_pymain")
|
||||||
|
self.assertEqual(out.rstrip(), "Py_Main() after Py_Initialize: sys.argv=['-c', 'arg2']")
|
||||||
|
self.assertEqual(err, '')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Py_Main() can again be called after Py_Initialize(), as in Python 3.6.
|
|
@ -2696,10 +2696,14 @@ pymain_main(_PyMain *pymain)
|
||||||
|
|
||||||
pymain_init_stdio(pymain);
|
pymain_init_stdio(pymain);
|
||||||
|
|
||||||
|
/* bpo-34008: For backward compatibility reasons, calling Py_Main() after
|
||||||
|
Py_Initialize() ignores the new configuration. */
|
||||||
|
if (!_PyRuntime.initialized) {
|
||||||
pymain->err = _Py_InitializeCore(&pymain->config);
|
pymain->err = _Py_InitializeCore(&pymain->config);
|
||||||
if (_Py_INIT_FAILED(pymain->err)) {
|
if (_Py_INIT_FAILED(pymain->err)) {
|
||||||
_Py_FatalInitError(pymain->err);
|
_Py_FatalInitError(pymain->err);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (pymain_init_python_main(pymain) < 0) {
|
if (pymain_init_python_main(pymain) < 0) {
|
||||||
_Py_FatalInitError(pymain->err);
|
_Py_FatalInitError(pymain->err);
|
||||||
|
|
|
@ -276,6 +276,21 @@ static int test_initialize_twice(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int test_initialize_pymain(void)
|
||||||
|
{
|
||||||
|
wchar_t *argv[] = {L"PYTHON", L"-c",
|
||||||
|
L"import sys; print(f'Py_Main() after Py_Initialize: sys.argv={sys.argv}')",
|
||||||
|
L"arg2"};
|
||||||
|
_testembed_Py_Initialize();
|
||||||
|
|
||||||
|
/* bpo-34008: Calling Py_Main() after Py_Initialize() must not crash */
|
||||||
|
Py_Main(Py_ARRAY_LENGTH(argv), argv);
|
||||||
|
|
||||||
|
Py_Finalize();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* *********************************************************
|
/* *********************************************************
|
||||||
* List of test cases and the function that implements it.
|
* List of test cases and the function that implements it.
|
||||||
|
@ -302,6 +317,7 @@ static struct TestCase TestCases[] = {
|
||||||
{ "pre_initialization_sys_options", test_pre_initialization_sys_options },
|
{ "pre_initialization_sys_options", test_pre_initialization_sys_options },
|
||||||
{ "bpo20891", test_bpo20891 },
|
{ "bpo20891", test_bpo20891 },
|
||||||
{ "initialize_twice", test_initialize_twice },
|
{ "initialize_twice", test_initialize_twice },
|
||||||
|
{ "initialize_pymain", test_initialize_pymain },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -772,6 +772,22 @@ _Py_InitializeCore(const _PyCoreConfig *core_config)
|
||||||
return _Py_INIT_OK();
|
return _Py_INIT_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Py_Initialize() has already been called: update the main interpreter
|
||||||
|
configuration. Example of bpo-34008: Py_Main() called after
|
||||||
|
Py_Initialize(). */
|
||||||
|
static _PyInitError
|
||||||
|
_Py_ReconfigureMainInterpreter(PyInterpreterState *interp,
|
||||||
|
const _PyMainInterpreterConfig *config)
|
||||||
|
{
|
||||||
|
if (config->argv != NULL) {
|
||||||
|
int res = PyDict_SetItemString(interp->sysdict, "argv", config->argv);
|
||||||
|
if (res < 0) {
|
||||||
|
return _Py_INIT_ERR("fail to set sys.argv");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _Py_INIT_OK();
|
||||||
|
}
|
||||||
|
|
||||||
/* Update interpreter state based on supplied configuration settings
|
/* Update interpreter state based on supplied configuration settings
|
||||||
*
|
*
|
||||||
* After calling this function, most of the restrictions on the interpreter
|
* After calling this function, most of the restrictions on the interpreter
|
||||||
|
@ -793,9 +809,6 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config)
|
||||||
if (!_PyRuntime.core_initialized) {
|
if (!_PyRuntime.core_initialized) {
|
||||||
return _Py_INIT_ERR("runtime core not initialized");
|
return _Py_INIT_ERR("runtime core not initialized");
|
||||||
}
|
}
|
||||||
if (_PyRuntime.initialized) {
|
|
||||||
return _Py_INIT_ERR("main interpreter already initialized");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get current thread state and interpreter pointer */
|
/* Get current thread state and interpreter pointer */
|
||||||
tstate = PyThreadState_GET();
|
tstate = PyThreadState_GET();
|
||||||
|
@ -810,6 +823,10 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config)
|
||||||
return _Py_INIT_ERR("failed to copy main interpreter config");
|
return _Py_INIT_ERR("failed to copy main interpreter config");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_PyRuntime.initialized) {
|
||||||
|
return _Py_ReconfigureMainInterpreter(interp, config);
|
||||||
|
}
|
||||||
|
|
||||||
if (interp->core_config._disable_importlib) {
|
if (interp->core_config._disable_importlib) {
|
||||||
/* Special mode for freeze_importlib: run with no import system
|
/* Special mode for freeze_importlib: run with no import system
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue