PyImport_ImportModule 和 import 语句是不是加载到不同的命名空间中?
Posted
技术标签:
【中文标题】PyImport_ImportModule 和 import 语句是不是加载到不同的命名空间中?【英文标题】:Do PyImport_ImportModule and import statement load into different namespace?PyImport_ImportModule 和 import 语句是否加载到不同的命名空间中? 【发布时间】:2011-12-21 09:06:09 【问题描述】:这里是 C/C++ 程序 extending embedded Python 3.x 的规范示例:
#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) 以使用 Python 3 调用的 C API 导入,那么行 (3 ) 产生错误:
Traceback (most recent call last):
File "<string>", line 1, in <module>
NameError: name 'emb' is not defined
我想了解这两种导入方式之间的区别。 他们是否将模块导入不同的namespaces / scopes?
Python 3 文档引导我走上了这条道路:
-
PyImport_ImportModule最好参考Python内置函数
__import__()
来描述
__import__()
函数由 import 语句调用。
也许我犯了一个错误,假设 PyImport_ImportModule
是一对一等价的,我应该将 PyImport_ImportModuleEx 与正确的(究竟是哪个?)全局变量和局部变量一起使用,所以我的“emb”位于我嵌入式的全局命名空间中口译员。
【问题讨论】:
【参考方案1】:__import__
根本不将模块放在任何命名空间中,而是返回它。
import
调用__import__
,并将结果存储在一个变量中。
docs 说 import spam
做了类似的事情:
spam = __import__('spam', globals(), locals(), [], 0)
要在 C API 中获得相同的效果,您需要分配给 emb
全局。也就是说,在__main__
模块上设置emb
属性。
PyObject* emb_module = PyImport_ImportModule("emb");
PyObject* main_module = PyImport_AddModule("__main__");
PyObject_SetAttrString(main_module, "emb", emb_module);
Py_XDECREF(emb_module);
/* (main_module is a borrowed reference) */
【讨论】:
+1 有效!我明白我的误解在哪里了。重新未经测试的代码,只是“emb”需要用 PyUnicode_FromString(“emb”) 包装。我还注意到获取 main 的快捷方式:PyObject* main_module = PyImport_AddModule("main"); 已编辑,谢谢。我使用了PyObject_SetAttrString
而不是PyUnicode_FromString
(更短,不用担心管理引用)。
我认为 PyImport_AddModule 的返回值是一个借用的引用,所以你不应该贬低它。以上是关于PyImport_ImportModule 和 import 语句是不是加载到不同的命名空间中?的主要内容,如果未能解决你的问题,请参考以下文章
PyImport_ImportModule("PyQt4.QtGui") 失败
C调用python——PyImport_ImportModule返回空指针
Julia Plots: PyCall.PyError("PyImport_ImportModule\n\npyimport 找不到 Python 包 matplotlib.pyplot