Search code examples
pythoncpython-modulepython-c-apipython-c-extension

python c api not able to import any module into the newly created module


Here is the code :

python_script[] = "try:\n\timport sys\nexcept:\n\tprint\"cannot import sys\"";
pNewMod = PyModule_New("mymod");
Py_Initialize();
pGlobal = PyDict_New();
pLocal = PyModule_GetDict(pNewMod);
PyRun_String(python_script, Py_file_input, pGlobal, pLocal);

I keep getting an exception at import sys and the message cannot import sys gets printed.

Also :

PyRun_SimpleString("import sys");
PyRun_SimpleString("print sys.path");

Works fine. I am not able to import any module into the newly created module.

Why am I not able to import any module? what am I missing here?


Solution

  • Resolved this in a different way : The problem is that the __dict__ attribute of a module is read-only.

    I am using the python/c api for 2.7.5. After using PyModule_New there was no provisioning to execute any code into the __dict__ for imports in the api. So I used a different approach.

    I created a module using python code rather than the python/c api. Which has the provision to to execute some code into a modules dictionary exec 'import sys' in mymod.__dict__.

    The sys import provides the newly created module to have access to sys.modules which has all the available modules. So when I do another import, the program knows where to look up the path for the import. Here is the code.

    PyRun_SimpleString("import types,sys");
    
    //create the new module in python 
    PyRun_SimpleString("mymod = types.ModuleType(\"mymod\")");
    
    //add it to the sys modules so that it can be imported by other modules
    PyRun_SimpleString("sys.modules[\"mymod\"] = mymod");
    
    //import sys so that path will be available in mymod so that other/newly created modules can be imported
    PyRun_SimpleString("exec 'import sys' in mymod.__dict__");
    
    //import it to the current python interpreter
    pNewMod=PyImport_Import(PyString_FromString("mymod"));
    
    //get the dict of the new module
    pLocal = PyModule_GetDict(pNewMod);
    
    //run the code that you want to be available in the newly created module.
    //python_script has the code that must be injected into the new module.
    //all your imports will work fine from now on. 
    //Provided that you have created them before importing sys in to the new module 
    PyRun_String(python_script, Py_file_input, pGlobal, pLocal);