Importing python file to c++ program - ModuleNotFoundError - python

Following this thread
Assume I have the following files in the directory prog:
main.cpp (located in the directory prog)
int main(int argc, char *argv[]){
Py_Initialize();
//Adding current path
PyObject* sys = PyImport_ImportModule("sys");
PyObject* path = PyObject_GetAttrString(sys, "path");
PyObject* cur_dir = PyUnicode_FromString("");
PyList_Append(path, cur_dir);
PyObject* myModuleString = PyUnicode_DecodeFSDefault((char*)"multiset_bell_numbers.py");
PyObject *pModule = PyImport_Import(myModuleString);
if (pModule == nullptr) {
PyErr_Print();
throw std::runtime_error("pModule is empty");
}
return 0;
}
multiset_bell_numbers.py (located in the directory prog)
from sympy.utilities.iterables import multiset_partitions
def calc_partitions(arr):
res = list(multiset_partitions(arr))
res.sort(key=lambda part:len(part))
return res
CMakeLists.txt
cmake_minimum_required(VERSION 3.24)
project(prog)
set(CMAKE_CXX_STANDARD 17)
find_package(Python REQUIRED COMPONENTS Interpreter Development)
include_directories(${Python_INCLUDE_DIRS})
add_executable(prog main.cpp)
target_link_libraries(prog ${Python_LIBRARIES})
But still got an error:
ModuleNotFoundError: No module named 'multiset_bell_numbers'
I have also tried to remove ".py" from the suffix of the string
What should I do?

In order for Python to find the multiset_bell_numbers module, it needs to be located in a directory that is in the Python Module Search Path.
The following directories will be checked:
The current folder from which the program executes.
A list of folders specified in the PYTHONPATH environment variable, if you set it before.
An installation-dependent list of folders that you configured when you installed Python.
If you ensure that the multiset_bell_numbers is in the same directory that the program is executed from, it should import successfully.
If that is not feasible, you can try updating PYTHONPATH to include the directory containing your module.

Related

PyImport_Import cannot find module

I'm trying to call a python function inside my c++
When i import my python module it gives this error:
ModuleNotFoundError: No module named 'test'
Here is how i'm importing the module:
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int main()
{
Py_Initialize();
PyObject *pName = PyUnicode_FromString("test");
PyObject *pModule = PyImport_Import(pName);
if (pModule == nullptr)
{
PyErr_Print();
std::exit(1);
}
Py_Finalize();
return 0;
}
I feel like this must have to do with my project structure. It currently looks like this:
project
|-- main.cpp
|-- test.py
I'm not sure if it's worth mentioning, but the executable is in the same directory, and it's being run from that directory aswell.
How can i fix this?
Use Py_SetPath before Py_Initialize() to set the sys.path.
Here is a longer list of what can be done before you initialize the interpreter: pre-init-safe
Isolate the embedded Python interpreter and set the path properly to avoid problems with partially using the modules of the installed Python version.
This was solved by setting the "PYTHONPATH" environment variable:
setenv("PYTHONPATH", ".", 1);
Thanks #Botje
As dwib mentioned I was able to overcome by the error by setting the PYTHONPATH variable in my zshrc (may be bashrc for you) file.
export PYTHONPATH=$PATH:/home/jk/jk/c
where /home/jk/jk/c is the folder where my file was residing.
Also sourced it
. ~/.zshrc

error: [WinError 2] The system cannot find the file specified while using distutils in python

I am trying to call a C function from Python (Extending Python with C).
I built a hello.c file and a setup.py file. When I run the setup file it's supposed to build a Python extension so that I can import it in Python.
But, when I try to run python setup.py install I am getting the error
error: [WinError 2] The system cannot find the file specified
I tried setting up the environmental variable, insert path in to sys, but still the error persists.
Can someone identify where I'm going wrong?
setup.py:
from distutils.core import setup, Extension
module1 = Extension('helloworld', sources = ['hello.c'])
setup(name='helloworld', version='1.0', ext_modules=[module1])
hello.c:
#include <Python.h>
static PyObject* helloworld(PyObject* self, PyObject* args) {
return Py_BuildValue("s", "Hello, Python extensions!!");
}
static char helloworld_docs[] =
"helloworld( ): Any message you want to put here!!\n";
static PyMethodDef helloworld_funcs[] = {
{"helloworld", (PyCFunction)helloworld,
METH_NOARGS, helloworld_docs},
{NULL}
};
void inithelloworld(void) {
Py_InitModule3("helloworld", helloworld_funcs,
"Extension module example!");
}
error:

"Segmentation fault" when run python function in C++ code using Cmake

I am learning to embed python code into c++ code. Following the simple example in How to solve the 'Segmentation fault' when hybrid programming of C & Python? and use g++ main.cpp -I/usr/include/python2.7 -L/usr/lib/python2.7 -lpython2.7 to compile the code and run the program, I can get the correct result.
But if I create a "build" folder and using CMake to run the program, it still has segmentation fault.
My CMakeList.txt is like below:
cmake_minimum_required(VERSION 2.8)
project ( pyTest )
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "RELEASE")
endif()
string(ASCII 27 Esc)
set(Red "${Esc}[1;31m")
set(ColourReset "${Esc}[m")
if(CMAKE_BUILD_TYPE MATCHES "DEBUG")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -O0 -g")
MESSAGE(STATUS "${Red}BUILD TYPE: DEBUG${ColourReset}")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -O3")
MESSAGE(STATUS "${Red}BUILD TYPE: RELEASE${ColourReset}")
endif()
include_directories( include )
find_package(PythonLibs REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS})
set(SRC_LIST2 main.cpp)
add_executable( pytest ${SRC_LIST2})
target_link_libraries(pytest ${PYTHON_LIBRARIES})
For convenience, I post my code below:
pytest.py
def Hello():
print "Hello, world!"
main.cpp
#include <Python.h>
int main()
{
Py_Initialize();
PyRun_SimpleString ("import sys; sys.path.insert(0, 'DIRECTORY_PATH'");
PyObject * pModule = NULL;
PyObject * pFunc = NULL;
pModule = PyImport_ImportModule("pytest");
pFunc = PyObject_GetAttrString(pModule, "Hello");
if(pFunc != NULL) {
PyEval_CallObject(pFunc, NULL);
Py_Finalize();
}
else {
printf("pFunc returned NULL\n");
}
return 0;
}
where "DIRECTORY_PATH" is the folder path of my main.cpp file and pytest.py, not the path of "build" folder
When I print out the result of PyImport_ImportModule, it returns 0. I think that means it doesn't get the python model. But my main.cpp and python file are under same directory, I don't know why it cannot get the model...
Can I fix it? Thx!
Solved by myself. I should put main.cpp and pytest.py under same directory and use PyRun_SimpleString ("import sys; sys.path.insert(0, 'DIRECTORY_PATH'"); to change 'DIRCTORY_PATH' to current directory that saves main.cpp and pytest.py. (Before I used a wrong dirctory so I got segmentation fault)

Boost python shared library issue in specific case

I am trying to extend my c++ library which is created using qtcreator to python with boost::python. I create a setup.py like following:
from distutils.core import setup
from distutils.extension import Extension
module1 = Extension('FOO',
include_dirs = ['/usr/include/python3.4', '/home/user/cppProjects/FOOLib','/usr/include', '/usr/local/lib/python3.4/dit-packages'],
libraries = ['python3.4', 'boost_python-py34', 'boost_thread', 'boost_system', 'FOOLib'],
library_dirs = ['/usr/lib/x86_64-linux-gnu/', '/usr/lib/python3.4/config-3.4m-x86_64-linux-gnu/','/home/skywalker/cppProjects/build-FOO-Desktop-Debug/'],
sources = ['pythonprovider.cpp'],
extra_compile_args=['-std=c++11'])
setup(name="PackageName",
ext_modules=[module1])
and Bar.h
class Bar
{
public:
Bar(boost::python::list args)
{
...
}
static void SetN(int n)
{
Bar::N = n;
}
static int N;
};
and Bar.cpp
int Bar::N;
pythonprovider.cpp is
BOOST_PYTHON_MODULE(FOO)
{
class_<Bar>("Bar", init<list>());
}
Compiling the library and using in c++ app is working fine.
I am typing the following code in terminal and installation of python module is working fine.
sudo python3 setup.py install
Including the package in python like
from FOO import *
working fine. But when i modify the pythonprovider.cpp with static method
BOOST_PYTHON_MODULE(FOO)
{
class_<Bar>("Bar", init<list>())
.def("SetN", &Bar::SetN)
.staticmethod("SetN");
}
compiling and installation working fine but importing the module assert an error
ImportError: libFOO.so.1: cannot open shared object file: No such file or directory
This happen to me before. When i move to body of constructor from cpp file to header file problem is solved but in this case it is not solve my problem.

Python dll Extension Import

I created extensions for my Python and created a abcPython.dll. How can I import this dll into my Python scripts?
I get an error message when I try to import it usin the following command
>>>import abcPython
>>>Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named abcPython
>>>
I manually created a system environment variable named PYTHONPATH which stores the path to the abcPython.dll, but still the error remains.
How can I fix this?
Follow Building C and C++ Extensions on Windows carefully - in sub-section 7, it says:
The output file should be called spam.pyd (in Release mode) or spam_d.pyd (in Debug mode). The extension .pyd was chosen to avoid confusion with a system library spam.dll to which your module could be a Python interface
...
Changed in version 2.5: Previously, file names like spam.dll (in release mode) or spam_d.dll (in debug mode) were also recognized.
Try the renaming your DLL to use a .pyd extension instead of .dll.
(thanks, Peter Hansen)
The reference points to a C example, which explicitly includes an INIT function,
PyMODINIT_FUNC initexample(void). The resulting DLL should be renamed example.pyd :
#include "Python.h"
static PyObject *
ex_foo(PyObject *self, PyObject *args)
{
printf("Hello, world\n");
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef example_methods[] = {
{"foo", ex_foo, METH_VARARGS, "foo() doc string"},
{NULL, NULL}
};
PyMODINIT_FUNC
initexample(void)
{
Py_InitModule("example", example_methods);
}
Aarrgghh! Yet another 2.X/3.X gotcha. RTFErrorMessage:
ImportError: dynamic module does not define init function (PyInit_abcPython)
Note the prefix: it's not init, it's PyInit_
See the 3.1 docs ... "The initialization function must be named PyInit_name(), where name is the name of the module"
Simple renaming of .dll to .pyd did not help. I was using SWIG to create the extension module. I created a .pyd instead of creating a .dll module and that solved the issue.
As an example: Imagine you have compiled OpenCV and have several *.dll and the cv2.pyd file.
You need to copy those files to 'DLLs' folder within the python directory.
Then import the module to check wether it is ok.

Categories