Issue
I am looking for a way of fully embedding python into a Qt application. With this, I mean that I want to build a Qt application that executes python code and I can fully distribute without having to care about which python version is installed in the target machine, or without having to ask the future user to install python by him/herself.
I’ve checked the libraries PythonQt, PyBind11, Boost.Python, and the native python libraries, and they are good to link C++ to Python, but any of them do what I want to do.
I have tried the following in Linux, and I was planning to do the same (or at least a similar approach) on Windows and Mac:
-
Download source code of Python (In my case, Python 3.9).
-
Build python.
mkdir build cd build ../configure --enable-optimizations --enable-shared make make install DESTDIR=installed/
-
Copy contents of installed into the dependencies folder of my projects. The contents of installer are the following folders:
- bin: Contains python executable and some tools like pip. - include: Contains all of the headers of python. - lib: Contains the .so libraries and the python modules (if you install a new python module using pip, it will be installed here in python3.9/site-packages/). - shared: Contains the man entries of python.
Having Python3.9 build, I have not installed any library yet, to test if this is the python that C++ is calling.
I have linked it from my Qt application in my .pro file like this:
INCLUDEPATH += $$PWD/../dependencies/python3.9/linux/include/python3.9
DEPENDPATH += $$PWD/../dependencies/python3.9/linux/include/python3.9
LIBS += -L$$PWD/../dependencies/python3.9/linux/lib/ -lpython3.9
Once linked, I call python like this:
Py_SetPythonHome(L"/link/to/dependencies/python3.9/linux/lib/python3.9/");
Py_SetPath(L"/link/to/dependencies/python3.9/linux/lib/python3.9/");
wchar_t *program = Py_DecodeLocale("", NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
exit(1);
}
Py_SetProgramName(program); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("import pgmpy");
if (Py_FinalizeEx() < 0) {
exit(120);
}
PyMem_RawFree(program);
In this code, I am importing the library pgmpy
. This package is not installed in the version of python I have build. However, it is installed in my local version of python, meaning that it is not using the python I have build, even when this is the one linked.
Is there any configuration step or something that I have missing? Is this ever feasible? I am more interested in solutions that are not specific to Qt, but can be applied to any C++ project, that is one of the reasons why I am using pybind11 and not pythonQt
Thank you.
Solution
I finally found a workaround.
I executed the python interpreter from terminal, and printed sys.path, showing the correct paths.
Then, in C++, I appended the correct paths to sys.path, removing the wrong ones.
Answered By – Alberto Casas Ortiz
Answer Checked By – Willingham (BugsFixing Volunteer)