包含属性的python类的ruamel.yaml转储似乎会产生意外的yaml格式

2024-05-04 22:53:22 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在将python类数据转储到YAML,以便稍后加载。我发现在ruamel.yaml(和PyYAML)中,当我使用属性来管理类属性转储类时,yaml输出会更改为似乎无效的yaml语法。我将下面的代码放在一起演示该行为

import sys
import ruamel.yaml

class MySampleClass(object):
    def __init__(self, attribute1, attribute2):
        self.attribute1 = attribute1
        self.attribute2 = attribute2

    @property
    def attribute1(self):
        return self.attribute1

    @attribute1.setter
    def attribute1(self, attribute1):
        self.__attribute1 = attribute1


sample1 = MySampleClass("ABCD", "123")
yaml = ruamel.yaml.YAML()
yaml.register_class(MySampleClass)
yaml.dump(sample1, sys.stdout)

运行时,将生成以下输出。正如您所看到的,修饰后的第一个属性具有意外的格式,而第二个属性是人们期望从YAML中得到的

!MySampleClass
_MySampleClass__attribute1: ABCD
attribute2: '1234'

有没有一种方法可以克服这一问题,而不必从头开始为每个类编写自定义构造函数和representer


Tags: 数据importselfyaml属性defsysruamel
1条回答
网友
1楼 · 发布于 2024-05-04 22:53:22

ruamel.yaml不会将属性/设置器作为“正常”属性处理,这就是为什么会得到有趣的输出,是有效的YAML

首先,您应该更改attribute1属性,因为调用print(sample1.attribute1)将 让你进入无限递归

然后,您可以创建一个基类,该基类具有适当的to_yaml方法 可用于转储所有类:

import sys
import ruamel.yaml
yaml = ruamel.yaml.YAML()

class ObjWithProperties(object):
    @classmethod
    def to_yaml(cls, representer, node):
        tag = getattr(cls, 'yaml_tag', '!' + cls.__name__)
        attribs = {}
        for x in dir(node):
            if x.startswith('_'):
                continue
            v = getattr(node, x)
            if callable(v):
                continue            
            attribs[x] = v
        return representer.represent_mapping(tag, attribs)


@yaml.register_class
class MySampleClass(ObjWithProperties):
    def __init__(self, attribute1, attribute2):
        self.attribute1 = attribute1
        self.attribute2 = attribute2

    @property
    def attribute1(self):
        return self.__attribute1  # <<<< note the added double underscore to prevent recursion

    @attribute1.setter
    def attribute1(self, attribute1):
        self.__attribute1 = attribute1


sample1 = MySampleClass("ABCD", "123")
yaml.dump(sample1, sys.stdout)

其中:

!MySampleClass
attribute1: ABCD
attribute2: '123'

相关问题 更多 >