Home > Mobile >  Importing a Python module in C
Importing a Python module in C

Time:06-02

I'm trying to port some Python 2 code to Python 3. In the code there is a module that is initialized in the C part that is later invoked by the python code. However my python code does not see the module that was initialized in C. Here is a simplified example:

#include <Python.h>
#include <stdio.h>

static PyMethodDef BenchMethods[] = {
        {NULL, NULL, 0, NULL}
};

int main(int argc, char **argv)
{
        PyObject *module;

        Py_SetProgramName(argv[0]);
        Py_Initialize();

        static struct PyModuleDef benchdef = {
                PyModuleDef_HEAD_INIT,
                "bench",
                NULL,
                -1,
                BenchMethods,
                NULL,
                NULL,
                NULL,
                NULL,
        };
        module = PyModule_Create(&benchdef);
        if (module == NULL) {
                printf("ERROR!\n");
                exit(0);
        }
        PyRun_SimpleString("import bench");

        Py_Finalize();
        return 0;
}

However upon compiling and trying to execute it I get an error:

$ gcc -I/path/to/include/python3.9 -o bench_simple.x bench_simple.c -L/path/to/lib -lpython3.9
$ ./bench_simple.x 
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'bench'

In Python 2 version the module is initialized via module = Py_InitModule("bench", BenchMethods);. I ported the code according to the instructions I found here

CodePudding user response:

PyModule_Create() (when successful) creates a module object. It does not load that object into any interpreter, and the fact that a module object has been created does not automatically put it in any interpreter's module load path. This is why the import bench in your example program fails.

The Python C API docs give specific instructions, supported by an example, for how an application embedding python can programmatically define a module and have the embedded interpreter load it. In a nutshell, the key is that instead of your application calling PyModule_Create() directly, it must

  1. define a module initialization function that makes that call and returns the result, and
  2. call PyImport_AppendInittab() to register that initialization function to the chosen module name, before initializing an interpreter.
  • Related