Why Does Pyimport_Import Fail to Load a Module from the Current Directory

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

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;
}

PyImport_Import cannot find module

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.

PyImport_Import fails to import module that contains imports

I found the solution. This happens because the debug symbols of numpy and scipy are missing. Setting visual studio in release mode solved the problem

PyImport_Import failing when submodules are imported in a python module

Use PyList_Insert in place of PyList_Append to get test imported from the location you want.

as @DavidW mentioned there is an importable module in the core libs called test.

change

PyList_Append(sysPath, PyUnicode_FromString("/jarvis_repo/src/cpp/packages/jarvis/nlp/"));

to

PyList_Insert(sysPath, 0, PyUnicode_FromString("/jarvis_repo/src/cpp/packages/jarvis/nlp/"));

so the test module is first found in /jarvis_repo/src/cpp/packages/jarvis/nlp/ and not in core libs.

Note: you should rename test instead

PyImport_Import fails (returns NULL)

I have resolved this issue by setting PYTHONPATH to pwd. Also module name (without .py) should be set for argv[1].

Thank you!

Python Embedding: PyImport_Import not from the current directory

Just found the answer I was looking for at http://realmike.org/blog/2012/07/08/embedding-python-tutorial-part-1/

Normally, when importing a module, Python tries to find the module
file next to the importing module (the module that contains the import
statement). Python then tries the directories in “sys.path”. The
current working directory is usually not considered. In our case, the
import is performed via the API, so there is no importing module in
whose directory Python could search for “shout_filter.py”. The plug-in
is also not on “sys.path”. One way of enabling Python to find the
plug-in is to add the current working directory to the module search
path by doing the equivalent of “sys.path.append(‘.’)” via the API.

Py_Initialize();
PyObject* sysPath = PySys_GetObject((char*)"path");
PyObject* programName = PyString_FromString(SplitFilename(argv[1]).c_str());
PyList_Append(sysPath, programName);
Py_DECREF(programName);

SplitFilename is a function I wrote to get the directory.

Why does importing a dotted module name fail when upper level is matched by a module in current directory?

An import statement like import foo.bar.baz first imports foo, then asks it for bar, and then asks foo.bar for baz. Whether foo will, once imported, be able to satisfy the request for bar or bar.baz is unimportant to the import of foo. It's just a module. There is only one foo module. Both import foo and import foo.bar.baz will find the same module -- just like any other way of importing the foo module.

There is actually a way for foo to be a single module, rather than a package, and still be able to satisfy a statement like import foo.bar.baz: it can add "foo.bar" and "foo.bar.baz" to the sys.modules dict. This is exactly what the os module does with os.path: it imports the right "path" module for the platform (posixpath, ntpath, os2path, etc), and assigns it to the path attribute. Then it does sys.modules["os.path"] = path to make that module importable as os.path, so a statement like import os.path works. There isn't really a reason to do this -- os.path is available without importing it as well -- but it's possible.

how to load a custom python module in c

I think it should be in the same directory or in sys.path as it loads a module by name, this should work:

./call multiply multiply 5 6

Update: if I add the current directory explicitly to sys.path it works:

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

And this prints:

./call multiply multiply 5 6
('Will compute', 5, 'times', 6)
Result of call: 30

Update: I've asked a relevant question and it seems that if you just add PySys_SetArgv instead it works:

Py_Initialize();
PySys_SetArgv(argc, argv);

The reason is mentioned here:

Otherwise (that is, if argc is 0 or argv[0] doesn’t point to an
existing file name), an empty string is prepended to sys.path, which
is the same as prepending the current working directory (".")

And this is the question you can check the answers there too:

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

PyImport_Import fails - Returns NULL

I thought that PyBytes_FromString was the the 3.x alternative of PyString_From.

I was wrong. PyUnicode_FromString is the correct alternative.

(Thanks to @wakjah for given me the tip of using error handling)



Related Topics



Leave a reply



Submit