模块对象¶
-
PyTypeObject
PyModule_Type
¶ 这个 C 类型实例
PyTypeObject
用来表示Python中的模块类型。在 Python 程序中该实例被暴露为types.ModuleType
。
-
int
PyModule_CheckExact
(PyObject *p)¶ 当 p 为模块类型的对象且不是
PyModule_Type
的子类型的对象时返回真值。该函数永远有返回值。
-
PyObject*
PyModule_NewObject
(PyObject *name)¶ - Return value: New reference.
返回新的模块对象,其属性
__name__
为 name 。模块的如下属性__name__
,__doc__
,__package__
, and__loader__
都会被自动填充。(所有属性除了__name__
都被设为None
)。调用时应当提供__file__
属性。3.3 新版功能.
在 3.4 版更改: 属性
__package__
和__loader__
被设为None
。
-
PyObject*
PyModule_New
(const char *name)¶ - Return value: New reference.
这类似于
PyModule_NewObject()
, 但其名称为 UTF-8 编码的字符串而不是 Unicode 对象。
-
PyObject*
PyModule_GetDict
(PyObject *module)¶ - Return value: Borrowed reference.
返回实现 module 的命名空间的字典对象;此对象与模块对象的
__dict__
属性相同。 如果 module 不是一个模块对象(或模块对象的子类型),则会引发SystemError
并返回NULL
。建议扩展使用其他
PyModule_*()
andPyObject_*()
函数而不是直接操纵模块的__dict__
。
-
PyObject*
PyModule_GetNameObject
(PyObject *module)¶ - Return value: New reference.
返回 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)¶ - Return value: New reference.
返回使用 module 的
__file__
属性所加载的 模块 的文件名。 如果属性未定义,或者如果它不是一个 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()
传入一个模块定义实例,并返回结果模块对象,或者通过返回定义结构体本身来请求“多阶段初始化”。
-
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
。
-
traverseproc
m_traverse
¶ 在模块对象的垃圾回收遍历期间所调用的遍历函数,如果不需要则为
NULL
。如果模块状态已被请求但尚未被分配,则不会调用此函数。例如在模块刚刚创建完成之后、被执行之前(
Py_mod_exec
函数)时的情况。更准确地说,如果m_size
大于0,并且模块状态(由PyModule_GetState()
返回)为NULL
,则不会调用此函数。在 3.9 版更改: 在模块状态被分配之前不再调用。
-
inquiry
m_clear
¶ 在模块对象的垃圾回收清理期间所调用的清理函数,如果不需要则为
NULL
。如果模块状态已被请求但尚未被分配,则不会调用此函数。例如在模块刚刚创建完成之后、被执行之前(
Py_mod_exec
函数)时的情况。更准确地说,如果m_size
大于0,并且模块状态(由PyModule_GetState()
返回)为NULL
,则不会调用此函数。就像
PyTypeObject.tp_clear
那样,这个函数并不总是在模块被释放前被调用。例如,当引用计数足以确定一个对象不再被使用时,就会直接调用m_free
,而不使用循环垃圾回收器。在 3.9 版更改: 在模块状态被分配之前不再调用。
-
freefunc
m_free
¶ 在模块对象的释放期间所调用的函数,如果不需要则为
NULL
。如果模块状态已被请求但尚未被分配,则不会调用此函数。例如在模块刚刚创建完成之后、被执行之前(
Py_mod_exec
函数)时的情况。更准确地说,如果m_size
大于0,并且模块状态(由PyModule_GetState()
返回)为NULL
,则不会调用此函数。在 3.9 版更改: 在模块状态被分配之前不再调用。
-
PyModuleDef_Base
单阶段初始化¶
模块初始化函数可以直接创建并返回模块对象,称为“单阶段初始化”,使用以下两个模块创建函数中的一个:
-
PyObject*
PyModule_Create
(PyModuleDef *def)¶ - Return value: New reference.
创建一个新的模块对象,在参数 def 中给出定义。它等同于将参数 module_api_version 设置为
PYTHON_API_VERSION
的PyModule_Create2()
函数。
-
PyObject*
PyModule_Create2
(PyModuleDef *def, int module_api_version)¶ - Return value: New reference.
创建一个新的模块对象,在参数 def 中给出定义,设定API版本为参数 module_api_version 。如果该版本与正在运行的解释器版本不匹配,则会触发
RuntimeWarning
。注解
大多数时候应该使用
PyModule_Create()
代替使用此函数,除非你确定需要使用它。
Before it is returned from in the initialization function, the resulting module
object is typically populated using functions like PyModule_AddObject()
.
多阶段初始化¶
另一种指定扩展的方式是“多阶段初始化”。以这种方式创建的扩展模块的行为更类似 Python 模块:初始化分成两个阶段,创建阶段 创建模块对象,执行阶段 填充模块对象。它们的区别类似类的 __new__()
和 __init__()
方法。
与使用单阶段初始化创建的模块不同,这些模块不是单例:如果 sys.modules 被移除、模块被重新导入,将会创建一个新的模块对象,旧模块将进入常规的垃圾回收——就像 Python 模块那样。默认情况下,根据同一个定义创建的多个模块应该是相互独立的:修改其中之一不应该影响其它模块。这意味着所有状态都应该特定于模块对象(例如使用 PyModule_GetState()
),或是它的内容(例如模块的 __dict__
属性,或是使用 PyType_FromSpec()
创建的独立的类)。
所有使用多阶段初始化创建的模块都应该支持 子解释器。保证多个模块之间相互独立,通常就可以实现这一点。
要请求多阶段初始化,初始化函数 (PyInit_modulename) 返回一个包含非空的 m_slots
属性的 PyModuleDef
实例。在它被返回之前,这个 PyModuleDef
实例必须先使用以下函数初始化:
-
PyObject*
PyModuleDef_Init
(PyModuleDef *def)¶ - Return value: Borrowed reference.
确保模块定义是一个正确初始化的Python对象,拥有正确的类型和引用计数。
返回转换为
PyObject*
的 def ,如果发生错误,则返回NULL
。3.5 新版功能.
模块定义的 m_slots 成员必须指向一个 PyModuleDef_Slot
结构体数组:
m_slots 数组必须以一个 id 为 0 的槽位结束。
可用的槽位类型是:
-
Py_mod_create
¶ 指定一个函数供调用以创建模块对象本身。 该槽位的 value 指针必须指向一个具有如下签名的函数:
-
PyObject*
create_module
(PyObject *spec, PyModuleDef *def)¶
该函数接受一个
ModuleSpec
实例,如 PEP 451 所定义的,以及模块定义。 它应当返回一个新的模块对象,或者设置一个错误并返回NULL
。此函数应当保持最小化。 特别地,它不应当调用任意 Python 代码,因为尝试再次导入同一个模块可能会导致无限循环。
多个
Py_mod_create
槽位不能在一个模块定义中指定。如果未指定
Py_mod_create
,导入机制将使用PyModule_New()
创建一个普通的模块对象。 名称是获取自 spec 而非定义,以允许扩展模块动态地调整它们在模块层级结构中的位置并通过符号链接以不同的名称被导入,同时共享同一个模块定义。不要求返回的对象必须为
PyModule_Type
的实例。 任何类型均可使用,只要它支持设置和获取导入相关的属性。 但是,如果PyModuleDef
具有非NULL
的m_traverse
,m_clear
,m_free
;非零的m_size
;或者Py_mod_create
以外的槽位则只能返回PyModule_Type
的实例。-
PyObject*
-
Py_mod_exec
¶ 指定一个供调用以 执行 模块的函数。 这造价于执行一个 Python 模块的代码:通常,此函数会向模块添加类和常量。 此函数的签名为:
如果指定了多个
Py_mod_exec
槽位,将按照它们在*m_slots*数组中出现的顺序进行处理。
有关多阶段初始化的更多细节,请参阅PEP:489
底层模块创建函数¶
当使用多阶段初始化时,将会调用以下函数。例如,在动态创建模块对象的时候,可以直接使用它们。注意,必须调用 PyModule_FromDefAndSpec
和 PyModule_ExecDef
来完整地初始化一个模块。
-
PyObject *
PyModule_FromDefAndSpec
(PyModuleDef *def, PyObject *spec)¶ - Return value: New reference.
创建一个新的模块对象,在参数 module 和 spec 中给出定义。它等同于将参数 module_api_version 设置为
PYTHON_API_VERSION
的PyModule_FromDefAndSpec2()
函数。3.5 新版功能.
-
PyObject *
PyModule_FromDefAndSpec2
(PyModuleDef *def, PyObject *spec, int module_api_version)¶ - Return value: New reference.
创建一个新的模块对象,在参数 module 和 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*。当使用
PyModule_Create
或PyModule_FromDefAndSpec
从PyModuleDef
创建模块时,会自动调用此函数。3.5 新版功能.
-
int
PyModule_AddFunctions
(PyObject *module, PyMethodDef *functions)¶ 将以
NULL
结尾的*functions*数组中的函数添加到*module*模块中。有关单个条目的更多细节,请参与PyMethodDef
文档(由于缺少共享的模块命名空间,在C中实现的模块级“函数”通常将模块作为它的第一个参数,与Python类的实例方法类似)。当使用PyModule_Create
或PyModule_FromDefAndSpec
从PyModuleDef
创建模块时,会自动调用此函数。3.5 新版功能.
支持函数¶
模块初始化函数(单阶段初始化)或通过模块的执行槽位调用的函数(多阶段初始化),可以使用以下函数,来帮助初始化模块的状态:
-
int
PyModule_AddObject
(PyObject *module, const char *name, PyObject *value)¶ Add an object to module as name. This is a convenience function which can be used from the module's initialization function. This steals a reference to value on success. Return
-1
on error,0
on success.注解
和其它窃取引用的函数不同,
PyModule_AddObject()
只在**成功**时减少*value*的引用计数。This means that its return value must be checked, and calling code must
Py_DECREF()
value manually on error. Example usage: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)¶ 将一个名称为*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*模块中。名称和值取自*macro*参数。例如,
PyModule_AddIntMacro(module, AF_INET)
将值为*AF_INET*的整型常量*AF_INET*添加到*module*模块中。如果发生错误,返回-1
,成功返回0
。
-
int
PyModule_AddType
(PyObject *module, PyTypeObject *type)¶ 将一个类型对象添加到 module 模块中。类型对象通过在函数内部调用
PyType_Ready()
完成初始化。类型对象的名称取自tp_name
最后一个点号之后的部分。如果发生错误,返回-1
,成功返回0
。3.9 新版功能.
查找模块¶
单阶段初始化创建可以在当前解释器上下文中被查找的单例模块。这使得仅通过模块定义的引用,就可以检索模块对象。
这些函数不适用于通过多阶段初始化创建的模块,因为可以从一个模块定义创建多个模块对象。
-
PyObject*
PyState_FindModule
(PyModuleDef *def)¶ - Return value: Borrowed reference.
返回当前解释器中由 def 创建的模块对象。此方法要求模块对象此前已通过
PyState_AddModule()
函数附加到解释器状态中。如果找不到相应的模块对象,或模块对象还未附加到解释器状态,返回NULL
。
-
int
PyState_AddModule
(PyObject *module, PyModuleDef *def)¶ 将传给函数的模块对象附加到解释器状态。 这将允许通过
PyState_FindModule()
来访问该模块对象。仅在使用单阶段初始化创建的模块上有效。
Python 会在导入一个模块后自动调用
PyState_AddModule
,因此从模块初始化代码中调用它是没有必要的(但也没有害处)。 显式的调用仅在模块自己的初始化代码后继调用了PyState_FindModule
的情况下才是必要的。 此函数主要是为了实现替代导入机制(或是通过直接调用它,或是通过引用它的实现来获取所需的状态更新详情)。调用时必须携带GIL。
成功是返回 0 或者失败时返回 -1。
3.3 新版功能.
-
int
PyState_RemoveModule
(PyModuleDef *def)¶ 从解释器状态中移除由 def 创建的模块对象。 成功时返回 0,者失败时返回 -1。
调用时必须携带GIL。
3.3 新版功能.