Python 3.10与3.11中Enum成员YAML序列化差异原因探究
Python 3.10与3.11中Enum序列化YAML的输出差异原因
测试代码
import sys import yaml try: from enum import ReprEnum except ImportError: from enum import Enum as ReprEnum class MyEnum(int, ReprEnum): foo = 123 print('Python version:', ''.join(map(str, sys.version_info[:3]))) print(yaml.dump({'test': MyEnum.foo}))
Python 3.10输出
Python version: 3.10.12 test: !!python/object/apply:__main__.MyEnum - 123
Python 3.11输出
Python version: 3.11.4 test: !!python/object/apply:builtins.getattr - !!python/name:__main__.MyEnum '' - foo
差异原因
这个差异完全源于Python 3.11对Enum模块序列化逻辑的改动,具体细节如下:
- 序列化核心逻辑变更
Python 3.10及更早版本中,Enum实例的序列化依赖「通过枚举值重建实例」的逻辑,对应实例的__reduce__方法会返回(枚举类, (成员值,)),PyYAML据此生成直接调用枚举类并传入值的YAML结构。
而Python 3.11开始,Enum改用「基于成员名称引用」的序列化方式,__reduce__方法返回(getattr, (枚举类, 成员名称))。这种改动是为了解决枚举类中可能存在的「值重复但成员名称不同」的场景,确保反序列化时能精准还原到对应的枚举成员,避免歧义。
- PyYAML的适配逻辑
PyYAML序列化Python对象时,会严格遵循对象__reduce__方法返回的信息生成对应YAML标签。因此当Enum的__reduce__返回值改变后,PyYAML输出的结构自然随之变化:
- 3.10版本直接调用枚举类构造实例
- 3.11版本通过
getattr从枚举类中获取指定名称的成员
内容的提问来源于stack exchange,提问作者ThiefMaster
相关产品推荐
相关产品推荐

