Вот канонический пример программы , расширяющей встроенный Python 3.x в C / C ++:
#include <Python.h>
//// Definition of 'emb' Python module ////////////////////
static PyObject* emb_foo(PyObject *self, PyObject *args)
{
char const* n = "I am foo";
return Py_BuildValue("s", n);
}
static PyMethodDef EmbMethods[] = {
{"foo", emb_foo, METH_VARARGS, "Returns foo"},
{NULL, NULL, 0, NULL}
};
static PyModuleDef EmbModule = {
PyModuleDef_HEAD_INIT, "emb", NULL, -1, EmbMethods,
NULL, NULL, NULL, NULL
};
static PyObject* PyInit_emb(void)
{
return PyModule_Create(&EmbModule);
}
//// Embedded Python with 'emb' loaded ////////////////////
int main()
{
PyImport_AppendInittab("emb", &PyInit_emb);
Py_Initialize();
PyRun_SimpleString("import emb\n"); // (1)
//PyImport_ImportModule("emb"); // (2)
PyRun_SimpleString("print(emb.foo())\n"); // (3)
Py_Finalize();
return 0;
}
Я добавляю модуль emb
во встроенные функции встроенного интерпретатора.
Я также хотел бы импортировать его автоматически, чтобы пользователям не приходилось использовать оператор import emb
в своих скриптах, предоставляемых моему встроенному интерпретатору.
Я пробую два способа импорта, в строках (1) и (2) .
(1) работает, и модуль emb
можно найти без явного импорта в простом тесте в строке (3) . Однако, если я закомментирую строку (1) и раскомментирую строку (2) для импорта через C API вызова Python 3, то строка (3) выдает ошибку:
Traceback (most recent call last):
File "<string>", line 1, in <module>
NameError: name 'emb' is not defined
Я бы хотел понять, в чем здесь разница между двумя способами импорта.
Импортируют ли они модуль в разные пространства имен / области ?
Документация по Python 3 повела меня по этому пути:
- PyImport_ImportModule лучше всего описывается с помощью встроенной функции Python
__import__()
__import__()
функция вызывается оператором импорта.
Возможно, я допустил ошибку, предполагая, что PyImport_ImportModule
является эквивалентом один к одному, и я должен использовать PyImport_ImportModuleEx с правильными (что именно?) Глобальными и локальными значениями, поэтому мой 'emb' находится в глобальном пространство имен моего встроенного интерпретатора.