Why does PyImport_Import fail to load a module from the current directory?

iabdalkader picture iabdalkader · Nov 16, 2012 · Viewed 9.6k times · Source

I'm trying to run the embedding example and I can't load a module from the current working directory unless I explicitly add it to sys.path then it works:

PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append(\".\")"); 

Shouldn't Python look for modules in the current directory ?

Edit1: Tried just importing the module with:

Py_Initialize();
PyRun_SimpleString("import multiply"); 

And it still fails with the following error:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
ImportError: No module named multiply

Edit2: From the sys.path docs:

If the script directory is not available (e.g. if the interpreter is invoked interactively or if the script is read from standard input), path[0] is the empty string, which directs Python to search modules in the current directory first.

Not sure what it means by not available, but if I print sys.path[0] it's not empty:

/usr/lib/pymodules/python2.7

Answer

Matti Lyra picture Matti Lyra · Nov 16, 2012

You need to call PySys_SetArgv(int argc, char **argv, int updatepath) for the relative imports to work. This will add the path of the script being executed to sys.path if updatepath is 0 (refer to the docs for more information).

The following should do the trick

#include <Python.h>

int
main(int argc, char *argv[])
{
  Py_SetProgramName(argv[0]);  /* optional but recommended */
  Py_Initialize();
  PySys_SetArgv(argc, argv); // must call this to get sys.argv and relative imports
  PyRun_SimpleString("import os, sys\n"
                     "print sys.argv, \"\\n\".join(sys.path)\n"
                     "print os.getcwd()\n"
                     "import thing\n" // import a relative module
                     "thing.printer()\n");
  Py_Finalize();
  return 0;
}