执行PyImport_ImportModule和import语句加载到不同的命名空间
Do PyImport_ImportModule and import statement load into different namespace?
这是一个扩展嵌入式Python 3程序的典型示例。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 embn"); // (1)
//PyImport_ImportModule("emb"); // (2)
PyRun_SimpleString("print(emb.foo())n"); // (3)
Py_Finalize();
return 0;
}
我将emb
模块添加到嵌入式解释器的内置模块中。我还想自动导入它,这样用户就不必在提供给我的嵌入式解释器的脚本中发出import emb
语句。我正在尝试两种导入方式,在(1)和(2)行。
(1)工作,在(3)行的简单测试中可以找到没有显式导入的emb
模块。但是,如果我注释掉(1)行并取消注释(2)行以导入Python 3调用的C API,那么(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__()
函数被import语句调用。
也许我犯了一个错误,假设PyImport_ImportModule
是一对一的等效,我应该使用PyImport_ImportModuleEx与正确的(确切地?)全局变量和局部变量,所以我的'emb'土地在我的嵌入式解释器的全局命名空间。
__import__
根本不把模块放在任何命名空间中,而是返回它。import
调用__import__
,并将结果存储在一个变量中。文档说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) */
相关文章:
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 无法在qsqlite中加载空间扩展(QT 5.9)
- 加载地址 X 时,对于 Y 类型的对象没有足够的空间
- 加载到阵列中会导致堆栈粉碎,同时有足够的空间
- 为什么主可执行文件和 dlopen 加载的共享库共享命名空间静态变量的一个副本?
- (重新)用空间index库加载R树
- 多个命名空间的动态加载
- C 的空间indexex库:从/到磁盘加载/存储主内存rtree
- 如何使用 strlen 计算空间并在 sprintf 中加载
- 断开命名管道(在加载表上)上的 SybaseIQ 问题
- 加载时重命名窗体MSVisual c++
- 如何判断共享库在进程地址空间中的加载位置
- 在C++命名空间中,当在头中声明的非成员子例程前面加前缀时,“static”限定符是否有任何作用
- 用简单的opengl图像库(SOIL)加载一张图像(颜色空间:GRAY)
- 执行PyImport_ImportModule和import语句加载到不同的命名空间
- DLL加载和系统映像空间
- C++ Win32 API 将驱动程序加载到内核空间
- 带和不带命名空间的加载时间差异
- 使用加载和保存方法对不同命名空间中的单个数据类型进行提升
- c++ #只包含加载一个命名空间