以编程方式在嵌入式 python 3 中定义包结构
Posted
技术标签:
【中文标题】以编程方式在嵌入式 python 3 中定义包结构【英文标题】:Programmatically define a package structure in embedded python 3 【发布时间】:2016-08-31 13:07:08 【问题描述】:我想创建一个嵌入式 python 3 解释器,并让 python 脚本导入通过 C Python API 创建的模块。
创建“***”模块没问题,但现在我想将我的模块组织在包中......但我失败了。
这是我当前的(简单)代码:
#include <Python.h>
//// Definition of 'emb.sub' module
static PyObject* emb_sub_foo(PyObject *self, PyObject *args)
char const* n = "I am sub foo";
return Py_BuildValue("s", n);
static PyMethodDef EmbSubMethods[] =
"foo", emb_sub_foo, METH_VARARGS, "Returns sub foo",
NULL, NULL, 0, NULL
;
static PyModuleDef EmbSubModule =
PyModuleDef_HEAD_INIT, "emb.sub", NULL, -1, EmbSubMethods,
NULL, NULL, NULL, NULL
;
static PyObject* PyInit_emb_sub(void)
return PyModule_Create(&EmbSubModule);
//// Embedded Python
int main()
PyImport_AppendInittab("emb.emb", &PyInit_emb_sub);
Py_Initialize();
PyRun_SimpleString("import emb.sub\n");
Py_Finalize();
return 0;
当我执行程序时,我得到:
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: No module named 'emb'
所以我创建了一个空的 emb 模块,并像这样设置它的__path__
:
#include <Python.h>
//// Definition of 'emb' module
static PyModuleDef EmbModule =
PyModuleDef_HEAD_INIT, "emb", NULL, -1, NULL,
NULL, NULL, NULL, NULL
;
static PyObject* PyInit_emb(void)
PyObject *mod = PyModule_Create(&EmbModule);
PyModule_AddObject(mod, "__path__", Py_BuildValue("()"));
return mod;
//// Definition of 'emb.sub' module
static PyObject* emb_sub_foo(PyObject *self, PyObject *args)
char const* n = "I am sub foo";
return Py_BuildValue("s", n);
static PyMethodDef EmbSubMethods[] =
"foo", emb_sub_foo, METH_VARARGS, "Returns sub foo",
NULL, NULL, 0, NULL
;
static PyModuleDef EmbSubModule =
PyModuleDef_HEAD_INIT, "emb.sub", NULL, -1, EmbSubMethods,
NULL, NULL, NULL, NULL
;
static PyObject* PyInit_emb_sub(void)
return PyModule_Create(&EmbSubModule);
//// Embedded Python
int main()
PyImport_AppendInittab("emb", &PyInit_emb);
PyImport_AppendInittab("emb.sub", &PyInit_emb_sub);
Py_Initialize();
PyRun_SimpleString("import emb.sub\n");
Py_Finalize();
return 0;
现在我得到了这个错误:
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: No module named 'emb.sub'
我想知道是否可以在嵌入式 python 中创建包和模块的层次结构?
谢谢!
【问题讨论】:
您找到解决方案了吗? @Ha11owed 最后我没有使用包,但接受了响应。 【参考方案1】:据我所知,默认的内置模块处理无法与包+模块名称匹配。这可以通过添加一个自定义导入钩子来解决,只需在 Py_Initialize() 之后运行它:
PyRun_SimpleString(
"import importlib.abc\n" \
"import importlib.machinery\n" \
"import sys\n" \
"\n" \
"\n" \
"class Finder(importlib.abc.MetaPathFinder):\n" \
" def find_spec(self, fullname, path, target=None):\n" \
" if fullname in sys.builtin_module_names:\n" \
" return importlib.machinery.ModuleSpec(\n" \
" fullname,\n" \
" importlib.machinery.BuiltinImporter,\n" \
" )\n" \
"\n" \
"\n" \
"sys.meta_path.append(Finder())\n" \
);
我用你的完整代码成功地尝试了这个:
#include <Python.h>
//// Definition of 'emb' module
static PyModuleDef EmbModule =
PyModuleDef_HEAD_INIT, "emb", NULL, -1, NULL,
NULL, NULL, NULL, NULL
;
static PyObject* PyInit_emb(void)
PyObject *mod = PyModule_Create(&EmbModule);
PyModule_AddObject(mod, "__path__", Py_BuildValue("()"));
return mod;
//// Definition of 'emb.sub' module
static PyObject* emb_sub_foo(PyObject *self, PyObject *args)
char const* n = "I am sub foo";
return Py_BuildValue("s", n);
static PyMethodDef EmbSubMethods[] =
"foo", emb_sub_foo, METH_VARARGS, "Returns sub foo",
NULL, NULL, 0, NULL
;
static PyModuleDef EmbSubModule =
PyModuleDef_HEAD_INIT, "emb.sub", NULL, -1, EmbSubMethods,
NULL, NULL, NULL, NULL
;
static PyObject* PyInit_emb_sub(void)
return PyModule_Create(&EmbSubModule);
//// Embedded Python
int main()
PyImport_AppendInittab("emb", &PyInit_emb);
PyImport_AppendInittab("emb.sub", &PyInit_emb_sub);
Py_Initialize();
PyRun_SimpleString(
"import importlib.abc\n" \
"import importlib.machinery\n" \
"import sys\n" \
"\n" \
"\n" \
"class Finder(importlib.abc.MetaPathFinder):\n" \
" def find_spec(self, fullname, path, target=None):\n" \
" if fullname in sys.builtin_module_names:\n" \
" return importlib.machinery.ModuleSpec(\n" \
" fullname,\n" \
" importlib.machinery.BuiltinImporter,\n" \
" )\n" \
"\n" \
"\n" \
"sys.meta_path.append(Finder())\n" \
);
PyRun_SimpleString("import emb.sub\n");
PyRun_SimpleString("print(emb.sub.foo())\n");
Py_Finalize();
return 0;
【讨论】:
您,先生,救了我的培根!谢谢。以上是关于以编程方式在嵌入式 python 3 中定义包结构的主要内容,如果未能解决你的问题,请参考以下文章
Xcode - 我如何以编程方式在容器视图中嵌入/更改视图控制器?