将数据类型声明为拉梅尔亚姆勒这样它就可以表达/序列化它?

2024-06-12 00:04:10 发布

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

我使用的是python库中的一个函数,它返回具有特定数据类型的对象。我想将该对象序列化为一个yaml文件,我想使用ruamel.yaml。问题是ruamel.yaml不知道如何序列化函数返回的特定数据类型并引发异常:

RepresenterError: cannot represent an object: <...>

问题是如何将数据类型“声明”为ruamel.yaml,以便它知道如何处理它。在

注意:我不能/我不想更改库或任何类似的内容。我只是API的消费者。在

为了使其更具体,让我们使用下面的示例,它使用^{},它恰好是一个^{},但具体的数据类型不应该很重要。在

^{pr2}$

这就产生了这个错误:

    ruamel.yaml.YAML.dump(self, data, stream, **kw)
  File "/home/feanor/Prog/git/vps-bench/.direnv/python-venv-3.7.2/lib/python3.7/site-packages/ruamel/yaml/main.py", line 439, in dump
    return self.dump_all([data], stream, _kw, transform=transform)
  File "/home/feanor/Prog/git/vps-bench/.direnv/python-venv-3.7.2/lib/python3.7/site-packages/ruamel/yaml/main.py", line 453, in dump_all
    self._context_manager.dump(data)
  File "/home/feanor/Prog/git/vps-bench/.direnv/python-venv-3.7.2/lib/python3.7/site-packages/ruamel/yaml/main.py", line 801, in dump
    self._yaml.representer.represent(data)
  File "/home/feanor/Prog/git/vps-bench/.direnv/python-venv-3.7.2/lib/python3.7/site-packages/ruamel/yaml/representer.py", line 84, in represent
    node = self.represent_data(data)
  File "/home/feanor/Prog/git/vps-bench/.direnv/python-venv-3.7.2/lib/python3.7/site-packages/ruamel/yaml/representer.py", line 111, in represent_data
    node = self.yaml_representers[data_types[0]](self, data)
  File "/home/feanor/Prog/git/vps-bench/.direnv/python-venv-3.7.2/lib/python3.7/site-packages/ruamel/yaml/representer.py", line 359, in represent_dict
    return self.represent_mapping(u'tag:yaml.org,2002:map', data)
  File "/home/feanor/Prog/git/vps-bench/.direnv/python-venv-3.7.2/lib/python3.7/site-packages/ruamel/yaml/representer.py", line 222, in represent_mapping
    node_value = self.represent_data(item_value)
  File "/home/feanor/Prog/git/vps-bench/.direnv/python-venv-3.7.2/lib/python3.7/site-packages/ruamel/yaml/representer.py", line 121, in represent_data
    node = self.yaml_representers[None](self, data)
  File "/home/feanor/Prog/git/vps-bench/.direnv/python-venv-3.7.2/lib/python3.7/site-packages/ruamel/yaml/representer.py", line 392, in represent_undefined
    raise RepresenterError('cannot represent an object: %s' % data)
ruamel.yaml.representer.RepresenterError: cannot represent an object: AddressFamily.AF_INET

Tags: gitselfyamlhomedatavenvvpslib
1条回答
网友
1楼 · 发布于 2024-06-12 00:04:10

为了使ruamel.yaml能够转储一个特定的类,无论您定义它,您都会得到它 从标准库或从其他地方获取if,您需要针对representer注册该类。 (在使用YAML(typ='unsafe')时,这是不必要的,但我假设您不想使用它)。在

这种注册可以用不同的方式进行。假设你有 完成yaml = ruamel.yaml.YAML()或{},并且想要表示SomeClass,您可以:

  • 使用yaml.register_class(SomeClass)。这可能适用于其他类,具体取决于 他们是如何定义的。在
  • 使用@yaml_object(yaml)或{},就在class SomeClass:之前 定义。这主要用于定义自己的类
  • 使用以下方法直接添加一个resenter: yaml.repenter.add_representer(某某类,某类,某类

前两种方法只是在第三种方法的基础上加上了语法糖 他们将尝试使用一个方法to_yaml和一个class属性 yaml_tag如果可用,那么尝试做一些合理的事情 无法使用的。在

您可以尝试yaml.register(socket.AF_INET),但您会注意到它失败的原因是:

AttributeError: 'AddressFamily' object has no attribute 'name'

所以你必须求助于第三种方法 add_representer()。参数some_class_to_yaml是一个函数 会的 当遇到SomeClass实例时调用,并调用该函数 使用yaml.representer实例作为第一个参数,并使用实际数据 (SomeClass的实例)作为第二个参数。在

如果SomeClass是某种容器类型,可以递归地(间接地)引用自身, 您需要特别注意处理这种可能性,但对于socket.AF_INET来说,这是不必要的。在

到目前为止,特定的数据类型非常重要,您需要决定 如何在YAML中表示类型。你会经常看到的 SomeClass的属性被用作映射中的键(然后是它 是获取标记的映射),但有时类型可以是 直接表示为YAML中可用的非集合类型,例如 作为一个字符串、int等,对于其他类来说,它是更有意义的 表示为(标记的)序列。在

当您打印type(socket.AF_INET)时,您会注意到“SomeClass”实际上是AddressFamily。 在使用dir()检查socket.AF_INET之后,您会注意到有一个name属性,并且 这很好地为您提供了一个字符串'AF_INET',它可以用来告诉representer 如何将此数据表示为字符串,而不必进行查找:

import sys
import socket
import ruamel.yaml


def repr_socket(representer, data):
    return representer.represent_scalar(u'!socket', data.name)

yaml = ruamel.yaml.YAML()
yaml.representer.add_representer(socket.AddressFamily, repr_socket)

data = dict(sock=socket.AF_INET)
yaml.dump(data, sys.stdout)

它给出了:

^{pr2}$

确保标记被定义为unicode(在使用python2.7时是必需的)。在

如果您还想加载这个,您可以用类似的方式扩展constructor。但是 这次您将得到一个Node,您需要将其转换为AddressFamily实例。在

^{3}$

它运行时不会引发异常,并显示另一个 也处理socket中的常量。在

相关问题 更多 >