PyModule_New 的用途和用法
Posted
技术标签:
【中文标题】PyModule_New 的用途和用法【英文标题】:Purpose and usage of PyModule_New 【发布时间】:2013-03-21 12:18:33 【问题描述】:表面上看,C-API 函数PyModule_New
和PyModule_NewObject
显然创建了一个新的模块对象。
official Python Documentation 为PyModule_NewObject
提供以下解释:
返回一个将 name 属性设置为 name 的新模块对象。 只填写模块的doc和name属性;这 调用者负责提供 file 属性。
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
的用途是什么?
【问题讨论】:
【参考方案1】:PyModule_New
是模块对象的构造函数。它也暴露给纯 Python 代码,作为 types.ModuleType
类的 __new__
方法。
用户代码可能很少需要使用其中任何一个,因为您通常通过导入它们来获取模块。但是,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
。
【讨论】:
以上是关于PyModule_New 的用途和用法的主要内容,如果未能解决你的问题,请参考以下文章