You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ruamel.yaml序列化含Enum的dataclass时from_yaml未调用致枚举还原失败

问题根因

from_yaml方法从未被调用的核心原因是自定义YAML标签不匹配:

  • 你在to_yaml实现里输出的枚举标签是!MyEnum:,末尾多写了一个冒号
  • @yaml_object(yaml)装饰器默认给MyEnum类注册的反序列化绑定标签是!MyEnum,没有末尾冒号
    标签无法对应时,ruamel.yaml找不到该节点关联的构造逻辑,就会把带未知标签的标量直接包装为TaggedScalar实例返回,自然不会触发你定义的枚举反序列化方法。

修正代码

删掉标签末尾多余的冒号即可,建议显式给类声明yaml_tag类属性固定标签值,避免装饰器隐式生成规则带来的匹配问题,修正后可直接运行的代码如下:

from dataclasses import dataclass
from ruamel.yaml import YAML, yaml_object
import enum

yaml = YAML()
write_file = "out.yaml"

@enum.unique
@yaml_object(yaml)
class MyEnum(enum.Enum):
    yaml_tag = "!MyEnum"
    ZERO = 0
    ONE = 1

    @classmethod
    def to_yaml(cls, representer, node):
        return representer.represent_scalar(cls.yaml_tag, node.name)

    @classmethod
    def from_yaml(cls, constructor, node):
        return cls[node.value]


@yaml_object(yaml)
@dataclass
class MyClass:
    yaml_tag = "!MyClass"
    foo: str
    bar: MyEnum

myobj = MyClass("hello", MyEnum.ZERO)

with open(write_file, "w", encoding="utf-8") as f:
    yaml.dump(myobj, f)

with open(write_file, "r", encoding="utf-8") as f:
    print(yaml.load(f))

运行效果

修正后序列化生成的out.yaml内容:

!MyClass
foo: hello
bar: !MyEnum ZERO

反序列化输出完全符合预期:

MyClass(foo='hello', bar=<MyEnum.ZERO: 0>)

补充说明

ruamel.yaml本身完全支持dataclass嵌套枚举的序列化/反序列化场景,不需要额外切换第三方库。如果确实有更复杂的类型嵌套序列化需求,可以在现有逻辑基础上扩展,不建议随意更换依赖。


内容的提问来源于stack exchange,提问作者cydonian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 13:09:17