模块对象 — Python 文档

来自菜鸟教程
Python/docs/3.8/c-api/module
跳转至:导航、​搜索

模块对象

PyTypeObject PyModule_Type
PyTypeObject 的这个实例表示 Python 模块类型。 这以 types.ModuleType 的形式暴露给 Python 程序。
int PyModule_Check(PyObject *p)
如果 p 是模块对象或模块对象的子类型,则返回 true。
int PyModule_CheckExact(PyObject *p)
如果 p 是模块对象,但不是 PyModule_Type 的子类型,则返回 true。
PyObject *PyModule_NewObject(PyObject *name)

返回一个新的模块对象,其中 __name__ 属性设置为 name。 模块的 __name____doc____package____loader__ 属性被填充(除了 __name__ 之外的所有属性都被设置为None); 调用者负责提供 __file__ 属性。

3.3 版中的新功能。

3.4 版本更改: __package____loader__ 设置为 None

PyObject *PyModule_New(const char *name)
类似于 PyModule_NewObject(),但名称是一个 UTF-8 编码的字符串,而不是一个 Unicode 对象。
PyObject *PyModule_GetDict(PyObject *module)

返回实现module命名空间的字典对象; 此对象与模块对象的 __dict__ 属性相同。 如果 module 不是模块对象(或模块对象的子类型),则引发 SystemError 并返回 NULL

建议扩展使用其他 PyModule_*PyObject_* 函数,而不是直接操作模块的 __dict__

PyObject *PyModule_GetNameObject(PyObject *module)

返回 module__name__ 值。 如果模块不提供,或者它不是字符串,则会引发 SystemError 并返回 NULL

3.3 版中的新功能。

const char *PyModule_GetName(PyObject *module)
类似于 PyModule_GetNameObject() 但返回编码为 'utf-8' 的名称。
void *PyModule_GetState(PyObject *module)
返回模块的“状态”,即指向模块创建时分配的内存块的指针,或NULL。 参见 PyModuleDef.m_size
PyModuleDef *PyModule_GetDef(PyObject *module)
返回指向创建模块的 PyModuleDef 结构的指针,如果模块不是从定义创建的,则返回 NULL 结构。
PyObject *PyModule_GetFilenameObject(PyObject *module)

使用 module__file__ 属性返回从中加载 module 的文件的名称。 如果未定义,或者它不是 unicode 字符串,则引发 SystemError 并返回 NULL; 否则返回对 Unicode 对象的引用。

3.2 版中的新功能。

const char *PyModule_GetFilename(PyObject *module)

类似于 PyModule_GetFilenameObject() 但返回编码为 'utf-8' 的文件名。

自 3.2 版起已弃用:PyModule_GetFilename() 在不可编码的文件名上引发 UnicodeEncodeError,请改用 PyModule_GetFilenameObject()

初始化 C 模块

模块对象通常从扩展模块(导出初始化函数的共享库)或编译模块(使用 PyImport_AppendInittab() 添加初始化函数)创建。 有关详细信息,请参阅 构建 C 和 C++ 扩展扩展嵌入式 Python

初始化函数可以将模块定义实例传递给 PyModule_Create(),并返回生成的模块对象,或者通过返回定义结构本身来请求“多阶段初始化”。

type PyModuleDef

模块定义结构,它包含创建模块对象所需的所有信息。 每个模块通常只有一个这种类型的静态初始化变量。

PyModuleDef_Base m_base

始终将此成员初始化为 PyModuleDef_HEAD_INIT

const char *m_name

新模块的名称。

const char *m_doc

模块的文档字符串; 通常使用 PyDoc_STRVAR 创建的文档字符串变量。

Py_ssize_t m_size

模块状态可以保存在每个模块的内存区域中,可以使用 PyModule_GetState() 检索,而不是在静态全局变量中。 这使得模块可以安全地用于多个子解释器。

该内存区域在模块创建时根据 m_size 分配,并在模块对象被释放时释放,在调用 m_free 函数后(如果存在)。

m_size 设置为 -1 表示该模块不支持子解释器,因为它具有全局状态。

将其设置为非负值意味着模块可以重新初始化并指定其状态所需的额外内存量。 多阶段初始化需要非负 m_size

有关更多详细信息,请参阅 PEP 3121

PyMethodDef *m_methods

指向模块级函数表的指针,由 PyMethodDef 值描述。 如果没有函数,可以是 NULL

PyModuleDef_Slot *m_slots

用于多阶段初始化的槽定义数组,由 {0, NULL} 条目终止。 使用单相初始化时,m_slots必须为NULL

3.5 版本变化: 在 3.5 版本之前,该成员始终设置为 NULL,并定义为:

inquiry m_reload


traverseproc m_traverse

在模块对象的 GC 遍历期间调用的遍历函数,或者 NULL 如果不需要。 该函数可以在分配模块状态之前调用(PyModule_GetState() 可能返回 NULL),并且在执行 Py_mod_exec 函数之前。

inquiry m_clear

在模块对象的 GC 清除期间调用的 clear 函数,或者 NULL 如果不需要。 该函数可以在分配模块状态之前调用(PyModule_GetState() 可能返回 NULL),并且在执行 Py_mod_exec 函数之前。

freefunc m_free

在模块对象释放期间调用的函数,或者 NULL 如果不需要。 该函数可以在分配模块状态之前调用(PyModule_GetState() 可能返回 NULL),并且在执行 Py_mod_exec 函数之前。

单相初始化

模块初始化函数可以直接创建并返回模块对象。 这称为“单阶段初始化”,并使用以下两个模块创建函数之一:

PyObject *PyModule_Create(PyModuleDef *def)
给定 def 中的定义,创建一个新的模块对象。 这就像 PyModule_Create2()module_api_version 设置为 PYTHON_API_VERSION
PyObject *PyModule_Create2(PyModuleDef *def, int module_api_version)

创建一个新的模块对象,给定 def 中的定义,假设 API 版本为 module_api_version。 如果该版本与正在运行的解释器的版本不匹配,则会发出 RuntimeWarning

笔记

这个函数的大多数用途应该使用 PyModule_Create() 代替; 只有在您确定需要它时才使用它。

在初始化函数中返回之前,生成的模块对象通常使用 PyModule_AddObject() 之类的函数填充。


多阶段初始化

指定扩展的另一种方法是请求“多阶段初始化”。 以这种方式创建的扩展模块的行为更像 Python 模块:初始化分为 创建阶段 (创建模块对象时)和 执行阶段 (填充时)。 区别类似于类的 __new__()__init__() 方法。

与使用单阶段初始化创建的模块不同,这些模块不是单例:如果删除 sys.modules 条目并重新导入模块,则会创建新的模块对象,并且旧模块是主题到正常的垃圾收集——就像 Python 模块一样。 默认情况下,从同一定义创建的多个模块应该是独立的:对一个模块的更改不应影响其他模块。 这意味着所有状态都应该特定于模块对象(使用例如 使用 PyModule_GetState()) 或其内容(例如模块的 __dict__ 或使用 PyType_FromSpec() 创建的单个类)。

使用多阶段初始化创建的所有模块都应支持 子解释器 。 确保多个模块是独立的通常足以实现这一点。

为了请求多阶段初始化,初始化函数 (PyInit_modulename) 返回一个 PyModuleDef 实例,其中包含非空 m_slots。 在返回之前,必须使用以下函数初始化 PyModuleDef 实例:

PyObject *PyModuleDef_Init(PyModuleDef *def)

确保模块定义是正确初始化的 Python 对象,可以正确报告其类型和引用计数。

如果发生错误,则将 def 转换为 PyObject*NULL

3.5 版中的新功能。

模块定义的 m_slots 成员必须指向一个 PyModuleDef_Slot 结构数组:

type PyModuleDef_Slot
int slot

从下面解释的可用值中选择的插槽 ID。

void *value

slot的值,其含义取决于slot ID。

3.5 版中的新功能。

m_slots 数组必须由一个 id 为 0 的插槽终止。

可用的插槽类型有:

Py_mod_create

指定被调用以创建模块对象本身的函数。 此槽的 value 指针必须指向签名的函数:

PyObject *create_module(PyObject *spec, PyModuleDef *def)

该函数接收 PEP 451 中定义的 ModuleSpec 实例和模块定义。 它应该返回一个新的模块对象,或者设置一个错误并返回 NULL

此功能应保持最小。 特别是,它不应调用任意 Python 代码,因为再次尝试导入相同的模块可能会导致无限循环。

一个模块定义中不能指定多个 Py_mod_create 插槽。

如果未指定 Py_mod_create,导入机制将使用 PyModule_New() 创建一个普通的模块对象。 该名称取自 spec,而不是定义,以允许扩展模块动态调整到它们在模块层次结构中的位置,并通过符号链接以不同的名称导入,同时共享单个模块定义。

不要求返回的对象是 PyModule_Type 的实例。 可以使用任何类型,只要它支持设置和获取导入相关的属性。 但是,如果 PyModuleDef 具有非 NULL m_traversem_clearm_free,则只能返回 PyModule_Type 实例; 非零 m_size; 或 Py_mod_create 以外的插槽。

Py_mod_exec

指定被调用以 执行 模块的函数。 这相当于执行 Python 模块的代码:通常,此函数向模块添加类和常量。 函数的签名是:

int exec_module(PyObject *module)

如果指定了多个 Py_mod_exec 插槽,则按照它们在 m_slots 数组中出现的顺序进行处理。

有关多阶段初始化的更多详细信息,请参阅 PEP 489


低级模块创建函数

使用多阶段初始化时,会在后台调用以下函数。 它们可以直接使用,例如在动态创建模块对象时。 请注意,必须调用 PyModule_FromDefAndSpecPyModule_ExecDef 来完全初始化模块。

PyObject *PyModule_FromDefAndSpec(PyModuleDef *def, PyObject *spec)

给定 module 和 ModuleSpec spec 中的定义,创建一个新的模块对象。 这就像 PyModule_FromDefAndSpec2()module_api_version 设置为 PYTHON_API_VERSION

3.5 版中的新功能。

PyObject *PyModule_FromDefAndSpec2(PyModuleDef *def, PyObject *spec, int module_api_version)

假设 API 版本为 module_api_version,给定 module 和 ModuleSpec spec 中的定义,创建一个新的模块对象。 如果该版本与正在运行的解释器的版本不匹配,则会发出 RuntimeWarning

笔记

这个函数的大多数用途应该使用 PyModule_FromDefAndSpec() 代替; 只有在您确定需要它时才使用它。

3.5 版中的新功能。

int PyModule_ExecDef(PyObject *module, PyModuleDef *def)

处理 def 中给出的任何执行槽 (Py_mod_exec)。

3.5 版中的新功能。

int PyModule_SetDocString(PyObject *module, const char *docstring)

module 的 docstring 设置为 docstring。 当使用 PyModule_CreatePyModule_FromDefAndSpecPyModuleDef 创建模块时,会自动调用此函数。

3.5 版中的新功能。

int PyModule_AddFunctions(PyObject *module, PyMethodDef *functions)

NULL 终止的 function 数组中的函数添加到 module。 有关各个条目的详细信息,请参阅 PyMethodDef 文档(由于缺少共享模块命名空间,在 C 中实现的模块级“函数”通常将模块作为它们的第一个参数,使它们类似于实例方法在 Python 类上)。 当使用 PyModule_CreatePyModule_FromDefAndSpecPyModuleDef 创建模块时,会自动调用此函数。

3.5 版中的新功能。


支持功能

模块初始化函数(如果使用单阶段初始化)或从模块执行槽调用的函数(如果使用多阶段初始化),可以使用以下函数来帮助初始化模块状态:

int PyModule_AddObject(PyObject *module, const char *name, PyObject *value)

添加一个对象到 module 作为 name。 这是一个方便的函数,可以从模块的初始化函数中使用。 这会在成功时窃取对 的引用。 出错时返回 -1,成功时返回 0

笔记

与其他窃取引用的函数不同,PyModule_AddObject() 仅在成功 时减少 value 的引用计数。

这意味着必须检查其返回值,并且调用代码必须在错误时手动 Py_DECREF() value。 用法示例:

Py_INCREF(spam);
if (PyModule_AddObject(module, "spam", spam) < 0) {
    Py_DECREF(module);
    Py_DECREF(spam);
    return NULL;
}
int PyModule_AddIntConstant(PyObject *module, const char *name, long value)
将整数常量添加到 module 作为 name。 这个方便的函数可以从模块的初始化函数中使用。 出错时返回 -1,成功时返回 0
int PyModule_AddStringConstant(PyObject *module, const char *name, const char *value)
将字符串常量添加到 module 作为 name。 这个方便的函数可以从模块的初始化函数中使用。 字符串 value 必须以 NULL 结尾。 出错时返回 -1,成功时返回 0
int PyModule_AddIntMacro(PyObject *module, macro)
module 添加一个 int 常量。 名称和值取自 macro。 例如,PyModule_AddIntMacro(module, AF_INET) 将值为 AF_INET 的 int 常量 AF_INET 添加到 module。 出错时返回 -1,成功时返回 0
int PyModule_AddStringMacro(PyObject *module, macro)
将字符串常量添加到 module


模块查找

单阶段初始化创建可以在当前解释器的上下文中查找的单例模块。 这允许稍后仅使用对模块定义的引用来检索模块对象。

这些函数不适用于使用多阶段初始化创建的模块,因为可以从单个定义创建多个此类模块。

PyObject *PyState_FindModule(PyModuleDef *def)
返回从 def 为当前解释器创建的模块对象。 此方法要求模块对象已预先使用 PyState_AddModule() 附加到解释器状态。 如果未找到相应的模块对象或尚未附加到解释器状态,则返回 NULL
int PyState_AddModule(PyObject *module, PyModuleDef *def)

将传递给函数的模块对象附加到解释器状态。 这允许通过 PyState_FindModule() 访问模块对象。

仅对使用单阶段初始化创建的模块有效。

Python在导入模块后会自动调用PyState_AddModule,因此从模块初始化代码中调用它是不必要的(但无害的)。 仅当模块自己的初始化代码随后调用 PyState_FindModule 时才需要显式调用。 该函数主要用于实现替代导入机制(通过直接调用它,或通过参考其实现以获取所需状态更新的详细信息)。

成功时返回 0,失败时返回 -1。

3.3 版中的新功能。

int PyState_RemoveModule(PyModuleDef *def)

从解释器状态中移除从 def 创建的模块对象。 成功时返回 0,失败时返回 -1。

3.3 版中的新功能。