Core: fix import of FreeCAD in a Python 3.12 interpreter

Importing FreeCAD as a module in a normal Python interpreter (e.g. /usr/bin/python3) stopped working with Python 3.12 (but works normally with Python 3.11). When executing "import FreeCAD as App", the interpreter crashes with "Fatal Python error: PyImport_AppendInittab: PyImport_AppendInittab() may not be called after Py_Initialize()".
The check that causes the error message and abortion was introduced in Python 3.12 via
https://github.com/python/cpython/commit/7f3a4b967cfb1596a3fda6c34f900f8586b16700
(and a typo in the error message fixed via)
https://github.com/python/cpython/commit/35dd55005ee9aea2843eff7f514ee689a0995df8
This commit is contained in:
bdieterm
2024-06-07 12:19:45 -05:00
committed by Chris Hennes
parent 5ca6eab922
commit ea68c5e88c
+28 -3
View File
@@ -2554,9 +2554,34 @@ void Application::initConfig(int argc, char ** argv)
mConfig["Debug"] = "0";
# endif
// init python
PyImport_AppendInittab ("FreeCAD", init_freecad_module);
PyImport_AppendInittab ("__FreeCADBase__", init_freecad_base_module);
if (!Py_IsInitialized()) {
// init python
PyImport_AppendInittab ("FreeCAD", init_freecad_module);
PyImport_AppendInittab ("__FreeCADBase__", init_freecad_base_module);
}
else {
// "import FreeCAD" in a normal Python 3.12 interpreter would raise
// Fatal Python error: PyImport_AppendInittab:
// PyImport_AppendInittab() may not be called after Py_Initialize()
// because the (external) interpreter is already initialized.
// Therefore we use a workaround as described in https://stackoverflow.com/a/57019607
PyObject *sysModules = PyImport_GetModuleDict();
const char *moduleName = "FreeCAD";
PyImport_AddModule(moduleName);
ApplicationMethods = Application::Methods;
PyObject *pyModule = init_freecad_module();
PyDict_SetItemString(sysModules, moduleName, pyModule);
Py_DECREF(pyModule);
moduleName = "__FreeCADBase__";
PyImport_AddModule(moduleName);
pyModule = init_freecad_base_module();
PyDict_SetItemString(sysModules, moduleName, pyModule);
Py_DECREF(pyModule);
}
const char* pythonpath = Base::Interpreter().init(argc,argv);
if (pythonpath)
mConfig["PythonSearchPath"] = pythonpath;