在PyYAML中使用自定义类键反序列化字典失败

问题描述 投票:1回答:1

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

AttributeError:'SampleClass'对象没有属性'name'

怎么解决这个问题? 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)))
python pyyaml
1个回答
0
投票

PyYAML有点过时,它只支持YAML 1.1,它在2009年被YAML 1.2取代。另请注意,虽然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_yaml提供from_yamlSampleClass例程并注册课程(doc)。这允许您取消不安全的加载(这是BTY默认的PyYAML)。

© www.soinside.com 2019 - 2024. All rights reserved.