--
#file func.py
def func1():
print "inside func1()"
--
//main.c
int main()
{
PyObject *pFunc, *pModule;
Py_Initialize();
pModule=PyImport_ImportModule("func"); //fileread.py
if(pModule==NULL)
{
PyErr_Print();
fprintf(stderr,"Failed to load \"%s\"\n","func");
}
//etc....
}
---
Both main.c and func.py are in the same directory.
I run main and get the error
Failed to load "func", meaning that PyImport_ImportModule returns NULL.
What am i doing wrong?
Thanks in advance for the help
Why do you try to load func, when the module is called fileread.py?
> PyErr_Print();
> fprintf(stderr,"Failed to load \"%s\"\n","func");
[...]
> What am i doing wrong?
You are not telling us what the Python exception was that you got.
Regards,
Martin
I know of at least four people who've given up on that route, and
instead done:
PyObject* res = PyRun_String("import module\n", Py_file_input, namesp,
namesp);
res will be NULL on error, a reference to Py_None otherwise. You can
grab a PyObject* to the module from the namespace dicts you passed in.
If anyone knows how to do it with purely API calls, I'm all ears <wink>.
-- bjorn
PyImport_ImportModule bypasses import hooks. PyImport_Import doesn't,
and thus it's what you should normally use unless you're specifically
_trying_ to bypass whatever hooks are set. Is that your problem...?
Alex
> I am trying to embed python within a c program, but I can't get
> PyImport_ImportModule() command to load my module.
> Please let me know what I'm doing wrong.
...
> Both main.c and func.py are in the same directory.
> I run main and get the error
> Failed to load "func", meaning that PyImport_ImportModule returns NULL.
The current directory is not necessarily on sys.path. Notice:
[alex@lancelot nubal]$ ./a.out
ImportError: No module named func
Failed to load "func"
[alex@lancelot nubal]$ PYTHONPATH=. ./a.out
inside func1()
[alex@lancelot nubal]$
I'm using the same code you posted plus the needed #include <Python.h>,
PyObject_CallMethod, and Py_Finalize.
You do need to ensure that the directories housing the modules you
want to import are on sys.path. For example, if you know they'll
be in your current directory, just add the line:
PySys_SetPath(".");
before you call PyImport_ImportModule, and your example will work.
Alex
You aren't doing anything wrong. I've tried to compile your code and it
didn't give me any errors.
I use MinGW GCC 2.95 under Windows 2000. You only forgot to #include
<Python.h>, but I don't think that's the problem.
Possibly, this is your compiler's fault. What compiler are you using, what
arguments are for it?
Lexy.
Hi Alex,
Perhaps you would know how to import a module so that it can be used in
PyRun_String()? I've tried PyImpor_Import, PyImport_ImportModule, and
PyImport_ImportModuleEx which all imported the module but didn't make it
visible.
void main() {
Py_Initialize();
PySys_SetPath(Py_GetPath());
PyObject* mainmod = PyImport_AddModule("__main__");
Py_INCREF(mainmod);
PyObject* ns = PyModule_GetDict(mainmod);
Py_INCREF(ns);
PyObject* timeModule = PyImport_ImportModuleEx("time", ns, ns,
NULL);
if (!timeModule) std::cout << getTraceback() << std::endl;
std::cout << "time module imported successfully" << std::endl;
PyObject* timeFn = PyRun_String("time.time", Py_eval_input, ns, ns);
if (!timeFn) std::cout << getTraceback() << std::endl;
Py_XDECREF(timeModule);
Py_XDECREF(timeFn);
Py_DECREF(ns);
Py_DECREF(mainmod);
Py_Finalize();
}
and the output:
Adding parser accelerators ...
Done.
time module imported successfully
Traceback (most recent call last):
File "<string>", line 0, in ?
NameError: name 'time' is not defined
[4099 refs]
-- bjorn
They give you the module object; if you want any object, including that
module you just imported, to be available under a name X in some
other module such as __main__, you set-attribute accordingly to bind
the name to the object. E.g. in the following snippet:
> void main() {
> Py_Initialize();
> PySys_SetPath(Py_GetPath());
>
>
> PyObject* mainmod = PyImport_AddModule("__main__");
> Py_INCREF(mainmod);
> PyObject* ns = PyModule_GetDict(mainmod);
> Py_INCREF(ns);
>
> PyObject* timeModule = PyImport_ImportModuleEx("time", ns, ns,
> NULL);
> if (!timeModule) std::cout << getTraceback() << std::endl;
> std::cout << "time module imported successfully" << std::endl;
you have the object timeModule and you want it to be visible in
module object mainmod under the name 'time', i.e., in dictionary
ns at key 'time'. So you can for example:
PyModule_AddObject(mainmod, "time", timeModule);
careful -- this steals a reference to timeModule, so incref it now
if you need it to stick around, or else just omit decref'ing it later.
Apart from this, the following code:
> PyObject* timeFn = PyRun_String("time.time", Py_eval_input, ns, ns);
>
> if (!timeFn) std::cout << getTraceback() << std::endl;
>
> Py_XDECREF(timeModule);
> Py_XDECREF(timeFn);
> Py_DECREF(ns);
> Py_DECREF(mainmod);
> Py_Finalize();
> }
should now work.
Python statement import does implicit binding -- you can see
import time
as equivalent to
time = __import__('time')
and at the C-API level you must use this more detailed approach -- it's
not QUITE as high-level as the Python statement 'import'!-)
Alex