在PyYAML中使用自定义类密钥对字典进行反序列化失败

时间:2019-03-13 10:04:41

标签: python pyyaml

我试图使用PyYAML来序列化一个字典,该字典使用SampleClass的实例作为键。它可以序列化OK,但是当我尝试用yaml.load()加载它时,会引发异常:

  

AttributeError:“ SampleClass”对象没有属性“名称”

如何解决? SampleClass的外观如下:

import uuid

class SampleClass:

    def __init__(self, name = "<NO NAME>"):
        self.objects = []
        self.name = name
        self.id = uuid.uuid1()

    def __eq__(self, other):
        if isinstance(other, SampleClass):
            return self.name == other.name and \
                self.objects == other.objects and \
                self.id == other.id
        else:
            return False

    def __hash__(self):
        return hash((str(self.name), str(self.id)))

1 个答案:

答案 0 :(得分:0)

PyYAML有点过时了,它仅支持已被YAML 1.2取代的YAML 1.1 早在2009年。还请注意,尽管PyYAML可以在YAML映射中解析复杂键(例如,序列或映射本身的键),但在YAML中有效的键却无法在Python中有效地构造它们无法加载这些。

使用ruamel.yaml(免责声明:我是该软件包的作者),您可以轻松执行以下操作:

import sys
import uuid
import ruamel.yaml
from ruamel.yaml.compat import StringIO

class SampleClass:

    def __init__(self, name = "<NO NAME>"):
        self.objects = []
        self.name = name
        self.id = uuid.uuid1()

    def __eq__(self, other):
        if isinstance(other, SampleClass):
            return self.name == other.name and \
                self.objects == other.objects and \
                self.id == other.id
        else:
            return False

    def __hash__(self):
        return hash((str(self.name), str(self.id)))

    def __repr__(self):
        return "SampleClass({})".format(self. name)

data = {SampleClass("abc"): 1, SampleClass("xyz"): 42}

yaml = ruamel.yaml.YAML(typ="unsafe")
buf = StringIO()
yaml.dump(data, buf)
x = yaml.load(buf.getvalue())
print(x)

给出:

{SampleClass(abc): 1, SampleClass(xyz): 42}

但是,我确实建议提供to_yamlfrom_yaml例程 到SampleClass并注册课程 (doc)。这个 允许您消除不安全的加载(顺便说一句 默认为PyYAML。