从表面看,C-API函数PyModule_New
和PyModule_NewObject
显然会创建一个新的模块对象。
official Python Documentation为PyModule_NewObject
提供了以下说明:
返回一个新模块对象,并将 name 属性设置为name。 仅填写模块的 doc 和名称属性;该 调用者负责提供文件属性。
PyModule_New
执行相同的操作,除了它接受C字符串(char*
)作为模块名称的参数,而不是PyObject*
字符串。
好的,所以这很简单,但是......
我的问题是:调用API函数PyModule_NewObject
有什么用?
当然,理论上对于想要动态创建新模块的情况来说会很棒。但问题在于,在实践中,在创建新的模块对象之后,对它做任何有用的事情的唯一方法是将对象(如方法,类,变量等)添加到模块的__dict__
属性中。这样,模块的用户可以导入它并实际执行某些操作。
问题是模块的__dict__
属性为 只读 :
>>> import re
>>> x = re
>>> re.__dict__ = { "foo" : "bar" }
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: readonly attribute
所以,实际上,就我所见,实际上没有办法对动态创建的模块做任何有用的事情。那么,C API函数的目的是什么呢PyModule_New
?
答案 0 :(得分:2)
PyModule_New
是模块对象的构造函数。作为__new__
类的types.ModuleType
方法,它也暴露于纯Python代码。
用户代码可能很少需要使用其中任何一种,因为您通常通过导入模块来获取模块。但是,Python解释器使用的机制在请求导入时使用PyModule_New
来创建模块对象。
您可以在import.c
in the Python source中看到这一点:
/* Get the module object corresponding to a module name.
First check the modules dictionary if there's one there,
if not, create a new one and insert it in the modules dictionary.
Because the former action is most common, THIS DOES NOT RETURN A
'NEW' REFERENCE! */
PyImport_AddModule(const char *name)
{
PyObject *modules = PyImport_GetModuleDict();
PyObject *m;
if ((m = PyDict_GetItemString(modules, name)) != NULL &&
PyModule_Check(m))
return m;
m = PyModule_New(name);
if (m == NULL)
return NULL;
if (PyDict_SetItemString(modules, name, m) != 0) {
Py_DECREF(m);
return NULL;
}
Py_DECREF(m); /* Yes, it still exists, in modules! */
return m;
}
至于如何在新模块对象中设置值,您可以使用常规属性访问。在Python代码(而不是C)中,这很简单:
import types
mymodule = types.ModuleType("mymodule")
mymodule.foo = "foo"
请注意,除非您执行其他工作,否则无法在其他任何位置导入以此方式创建的模块。例如,您可以将其添加到模块查找字典sys.modules
:
import sys
sys.modules["mymodule"] = mymodule
现在其他模块可以按名称导入mymodule
。