Skip to main content

模块对象

PyTypeObject PyModule_Type

这个 PyTypeObject 实例代表Python模块类型。这是暴露给Python程序为 types.ModuleType

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)
Return value: New reference.

PyImport_NewObject() 类似,但名称是UTF-8编码的字符串,而不是Unicode对象。

PyObject* PyModule_GetDict(PyObject *module)
Return value: Borrowed reference.

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

建议扩展使用其他 PyModule_*()PyObject_*() 功能,而不是直接操作模块的 __dict__

PyObject* PyModule_GetNameObject(PyObject *module)

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

3.3 新版功能.

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 新版功能.

char* PyModule_GetFilename(PyObject *module)

PyModule_GetFilenameObject() 类似,但返回编码为“utf-8”的文件名。

3.2 版后已移除: PyModule_GetFilename() 对不可编辑的文件名提出 UnicodeEncodeError,而改用 PyModule_GetFilenameObject()

初始化C模块

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

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

PyModuleDef

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

PyModuleDef_Base m_base

始终将此成员初始化为 PyModuleDef_HEAD_INIT

char* m_name

新模块的名称。

char* m_doc

Docstring模块;通常使用用 PyDoc_STRVAR() 创建的docstring变量。

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

inquiry m_clear

在GC清除模块对象期间调用的清除函数,如果不需要,则为 NULL

freefunc m_free

在释放模块对象期间调用的函数,如果不需要,则为 NULL

单相初始化

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

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)返回具有非空 m_slotsPyModuleDef 实例。在返回之前,必须使用以下函数初始化 PyModuleDef 实例:

PyObject* PyModuleDef_Init(PyModuleDef *def)

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

返回 def 转换为 PyObject*NULL (如果发生错误)。

3.5 新版功能.

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

PyModuleDef_Slot
int slot

插槽ID,从下面介绍的可用值中选择。

void* value

槽的值,其含义取决于槽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

指定一个被调用到 execute 模块的函数。这相当于执行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)

创建一个新的模块对象,给定 module 和ModuleSpec spec 中的定义,假设API版本为 module_api_version。如果该版本与正在运行的解释器的版本不匹配,则发出 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 终止的 functions 数组的函数添加到 module。参考 PyMethodDef 文档有关各个条目的详细信息(由于缺少共享模块命名空间,在C中实现的模块级“函数”通常接收模块作为它们的第一个参数,使它们类似于Python类的实例方法)。当使用 PyModule_CreatePyModule_FromDefAndSpecPyModuleDef 创建模块时,将自动调用此函数。

3.5 新版功能.

支持功能

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

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

将对象作为 name 添加到 module。这是一个方便的功能,可以从模块的初始化函数中使用。这偷了 value 的引用。返回 -1 错误,0 成功。

int PyModule_AddIntConstant(PyObject *module, const char *name, long value)

将整数常数作为 name 添加到 module。可以从模块的初始化函数使用此方便功能。返回 -1 时出错,0 成功。

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

将字符串常量作为 name 添加到 module。可以从模块的初始化函数使用此方便功能。字符串 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() 访问模块对象。

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

3.3 新版功能.

int PyState_RemoveModule(PyModuleDef *def)

从解释器状态删除从 def 创建的模块对象。

3.3 新版功能.