Python Limited API:如何设置扩展类型的__module__属性
Limited API下堆类型设置
__module__的实现方案 前置背景
- 使用Limited API开发Python C扩展时,无法直接访问
PyTypeObject结构体的内部字段,因此不能手动定义静态分配的类型对象 - 开发动态分配的堆类型时,仅可通过
PyType_Spec.name字段指定类型的基础名称 - 官方文档对堆类型的模块名配置有明确要求:
对于动态分配的类型对象,此处仅需填写类型名称,模块名需作为键
__module__对应的值显式存储在类型字典中。
常见实现误区
不少开发者会误以为公开的类型插槽体系中没有可直接配置PyTypeObject.tp_dict的入口,只能等PyType_FromSpec返回已创建的类型对象后,再手动操作类型字典补写__module__属性。
但这种实现的时机完全错误:Python解释器在类型创建的初始化阶段就会校验__module__属性的存在性,事后补写的操作无法满足校验逻辑,就会触发对应的弃用警告:DeprecationWarning: builtin type ... has no __module__ attribute
正确实现步骤
- 提前构造类型专属的字典对象,在字典中写入
__module__键,对应的值为类型所属模块的完整导入路径(例如"mypackage.mymodule") - 定义
PyType_Slot插槽数组时,追加对应Py_tp_dict的插槽项,将提前构造好的字典对象作为插槽值传入 - 调用
PyType_FromSpec创建类型时,该字典会直接被赋值给类型的tp_dict字段,从类型初始化的初始阶段就自带正确的__module__属性,完全不会触发弃用警告
操作注意事项
- 传入
Py_tp_dict插槽的字典对象,所有权会随类型创建流程转移给生成的类型对象,不需要在外部手动释放该字典,避免出现悬空指针 - 字典的引用计数管理要遵循Python C API的常规规则:如果是动态构造的临时字典,传入插槽前要确认引用计数符合所有权转移要求,不要在类型创建完成后再次手动递减该字典的引用计数
内容的提问来源于stack exchange,提问作者Michael Amrhein
相关产品推荐
相关产品推荐

