Building windows executable using pyqt with python embedded - python

I'm trying to make a windows application that runs some python code, more or less like what py2exe does but made by hand.
My application should run on windows without any external python dependencies (even the interpreter).
I've tested this (main.cpp):
#include <Python.h>
int main(int argc, char *argv[]) {
Py_SetProgramName(argv[0]);
Py_Initialize();
PyRun_SimpleString("print \"Test\"\n");
Py_Finalize();
return 0;
}
When a build this I get a .exe file which upon execution prints Test on the console.
So far so good, but now I'm trying to build a minimal PyQt application as well, for that I put on the same folder of my .exe application the files
QtGui.pyd, QtGui4.dll, QtCore.pyd and QtCore4.dll, this is main.cpp:
#include <Python.h>
int main(int argc, char *argv[]) {
Py_SetProgramName(argv[0]);
Py_Initialize();
PyRun_SimpleString("import QtGui as gui\n"
"\n"
"app = gui.QApplication([])\n"
"mw = gui.QMainWindow()\n"
"mw.show()\n"
"print \"Test\"\n"
"app.exec_()");
Py_Finalize();
return 0;
}
The problem is that when I run the built .exe file I got this error:
Traceback (most recent call last):
File "<string>", line 1, in <module>
SystemError: dynamic module not initialized properly
So I don't know what kind of initialization I need to do in order to use the .pyd files.
Finally these are my questions:
What I'm doing wrong?
If I need some kind of extra initialization, how could I do that and why it is needed? Maybe it's something inherent to the Qt bindings?
Should I copy another *pyd file to the working dir of the app?
Is this approach of using directly the .pyd files feasible? Or there is a better way to make an application like the one I want?
Note: I do not want to use any tool like py2exe, cx_Freeze, pyinstaller, etc. I want to build the app myself.

Related

Project File Line Suppression State Error LNK1104 cannot open file 'python310_d.lib'

I wrote a program for learning how to embed python in c++ . But when I try to run it in visual studio It shows a linker error that python310_d.lib is not found. I searched for this file in my python directory lib folder but there was no such file with this name. So now I need a way to somehow get that file. Please help me.
Here is my code
#include <iostream>
#include <Python.h>
using namespace std;
int main(int argc, char const* argv[])
{
Py_Initialize();
PyRun_SimpleString("print(\'Hellow Python\')");
Py_Finalize();
return 0;
}
Here are my errors
Severity Code Description Project File Line Suppression State
Error LNK1104 cannot open file 'python310_d.lib' Project1 C:\Users\noob\source\repos\Project1\Project1\LINK 1
It appears that the problem is you don't have the debug libraries installed. By default the installer will not install these unless you check the option to download these:
The picture and information for this answer was found in the following link:
https://github.com/pybind/pybind11/issues/3403#issuecomment-951485263

Can we create an .exe file that uses Python calls without having Python installed in the target machine?

I have this C code i took from https://docs.python.org/3/extending/embedding.html:
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int
main(int argc, char *argv[])
{
wchar_t *program = Py_DecodeLocale(argv[0], 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 numpy as np \n"
"student = np.dtype([('name','S20'), ('age', 'i1'), ('marks', 'f4')])\n"
"print(student)\n");
if (Py_FinalizeEx() < 0) {
exit(120);
}
PyMem_RawFree(program);
return 0;
}
It compiles and runs quite nicely in a machine that has python3 and python3-numpy installed.
The output:
[('name', 'S20'), ('age', 'i1'), ('marks', '<f4')]
However, if the target machine does not have numpy installed, the output is:
Traceback (most recent call last):
File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'numpy'
My question: is it possible to run the python code from the app executable in a target machine that has no Python3 nor numpy installed? If so, how do i do it?
I mostly thinking of Win10 as a target machine, but i guess my question would equally apply to other OSes.
Thanks!
EDIT: To be more exact, I am not asking if this code can be compiled without having Python installed. I know it must have some python-dev to be compiled.
But what I want to know is there a way to create an .exe file that uses some Python calls without having Python installed in the target machine?
Use PyInstaller. It will wrap your Python code, a Python interpreter, and the packages you need into a standalone .exe file.
Specifically, numpy is on the list of supported packages.
I would get rid of the C program, put your main Python code in a .py file, and let PyInstaller do the work for you.
This is a much better solution than requiring your users to have a Python interpreter installed, much less any particular libraries and packages. It allows each application to have its own version of Python and packages.
Full details are in the PyInstaller docs.

How to run Python code before `site` module is imported?

Is there a way to execute Python code before the site module is imported?
In case it matters, I'm asking because I'm running an embedded Python interpreter via Py_Initialize, and I'd like to configure the Python environment using Python code, however it's important this happens before the site module is imported since the changes impact how it initializes.
You can set Py_NoSiteFlag to suppress loading of site.py while initializing Python interpreter. site could be loaded later-on manually.
Here is a minimal example:
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int
main(int argc, char *argv[])
{
Py_NoSiteFlag = 1; /* Suppress 'import site' */
Py_Initialize();
PyRun_SimpleString("import sys; print('site' in sys.modules)\n");
//There are no site-packages in path:
PyRun_SimpleString("print(sys.path)\n");
// do what must be done
// ....
//now, import site manually,
//call site.main(), so site-packages are added to sys.path:
PyRun_SimpleString("import site; site.main()");
//now, site-packages are in path:
PyRun_SimpleString("print(sys.path)\n");
if (Py_FinalizeEx() < 0) {
exit(120);
}
return 0;
}
When running the resulting executable, one sees that site isn't loaded in Py_Initialize (first printed line is False) and is loaded later. We also need to call site.main() explicitly for site-packages to be put into sys.path.

import_array doesn't work in debug build in embedded Python C API

I have the following problem: I am using the embedded Python C API from C++ to execute Python code. Everything works so far in Release Mode, but as soon as I start to run the Debug Mode, I get the error:
ImportError: numpy.core.multiarray failed to import
when calling from C++:
Py_Initialize();
import_array();
Can anyone help me with that?
Thanks a lot in advance
Without seeing the full program code; if you check the docs, it recommends putting the line:
Py_SetProgramName(argv[0]); /* optional but recommended */
Before you make the Py_Initialize() function call.
"The Py_SetProgramName() function should be called before Py_Initialize() to inform the interpreter about paths to Python run-time libraries"
Make sure your main function has the argv argument like the example in the docs.
#include <Python.h>
int main(int argc, char *argv[])
{
Py_SetProgramName(argv[0]); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print 'Today is',ctime(time())\n");
Py_Finalize();
return 0;
}

Unable to call custom module using Python/C API

File structure:
Foo/
list.so
main.cpp
list.cpp
boost_wrapper.cpp
main.cpp code:
#include <Python.h>
#include "list.cpp"
int main(int argc, char *argv[]){
PyObject *pimport;
pimport=PyString_FromString("list");
Py_SetProgramName(argv[0]);
Py_Initialize();
PyImport_Import(pimport);
/*PyRun_SimpleString("l=list.LinkedList()");
PyRun_SimpleString("l.insert(\"N\", 9)");
PyRun_SimpleString("l.display()");*/
Py_Finalize();
}
ERROR:
ImportError: No module named list
However if I run python from bash, I'm able to successfully import the module and use all functions defined. I've also tried to import using just PyRun_SimpleString with no avail.
I suspect the current working directory is invisible to the Python Interpreter called by Py_Initialize().
Add these lines after Py_Initialize(); to append your PYTHONPATH
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append(\".\")");

Categories

Resources