【问题标题】:Deserializing YAML back into Python object将 YAML 反序列化回 Python 对象
【发布时间】:2018-01-09 00:07:04
【问题描述】:

我正在尝试将正确的 from_yaml 方法写入我的类,以便在使用 ruamel.yaml 库加载 YAML 文件时能够反序列化回它。

让我们假设在我的 to_yaml 类方法中我返回如下内容:

@classmethod
def to_yaml(cls, dumper, data):
    dict_representation = {
        'foo': data.foo, 
        'bar': data.bar
    }

    return dumper.represent_mapping(cls.yaml_tag, dict_representation)

现在在反序列化方法中

@classmethod
def from_yaml(cls, constructor, node):
    dict_representation = constructor.construct_mapping(node, deep=True)

有了这个我得到TypeError

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-6-782b00e19bec> in <module>()
----> 1 dict_representation = yaml.constructor.construct_mapping(node, deep=True)

/home/**/.envs/myenv/local/lib/python2.7/site-packages/ruamel/yaml/constructor.pyc in construct_mapping(self, node, maptyp, deep)
   1186                         "found unhashable key", key_node.start_mark)
   1187             value = self.construct_object(value_node, deep=deep)
-> 1188             self.check_mapping_key(node, key_node, maptyp, key, value)
   1189
   1190             if key_node.comment and len(key_node.comment) > 4 and \

/home/**/.envs/myenv/local/lib/python2.7/site-packages/ruamel/yaml/constructor.pyc in check_mapping_key(self, node, key_node, mapping, key, value)
    241     def check_mapping_key(self, node, key_node, mapping, key, value):
    242         # type: (Any, Any, Any, Any, Any) -> None
--> 243         if key in mapping:
    244             if not self.allow_duplicate_keys:
    245                 args = [

TypeError: argument of type 'NoneType' is not iterable

事实上,尝试在交互式 shell 中更凭经验做到这一点:

import ruamel.yaml
yaml = ruamel.yaml.YAML()
dd = {'foo': 'foo'}
node = yaml.representer.represent_mapping('!dd', dd)
dict_representation = yaml.constructor.construct_mapping(node)

引发相同的异常。我在这里错过了什么?

【问题讨论】:

  • 如果您发布异常的完整堆栈跟踪以及您正在使用的 yaml 库的名称,人们会更容易帮助您。

标签: python serialization yaml pyyaml ruamel.yaml


【解决方案1】:

为了让往返工作正常,RoundTripConstructor()construct_mapping() 需要获取传入的实际映射类型实例,因此可以从节点获取诸如 cmets 之类的内容并附加到该实例(通常是CommentedMap())。进行非往返加载时不需要该额外参数(因为不需要传递评论信息)。

该方法本可以设计得更智能,目前如果未提供映射类型,则默认为 None,这就是您获得 NoneType is not iterable 异常的地方。

要从问题末尾的代码开始,您可以通过以下方式调用更简单的映射构造函数:

dict_representation = ruamel.yaml.constructor.SafeConstructor.construct_mapping(
    yaml.constructor, node)

您的 from_yaml() 类方法应该以相同的方式工作:

@classmethod
def from_yaml(cls, constructor, node):
    dict_representation = ruamel.yaml.constructor.SafeConstructor.construct_mapping(
        constructor, node, deep=True)

虽然如果您正在构建复杂类型(其中一些间接可访问的值可能引用此节点),您应该考虑使用两步创建过程:

@classmethod
def from_yaml(cls, constructor, node):
    dict_representation = dict()
    yield dict_representation
    d = ruamel.yaml.constructor.SafeConstructor.construct_mapping(
         constructor, node, deep=True)
    dict_representation.update(d)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-06
    • 2013-08-21
    • 1970-01-01
    • 1970-01-01
    • 2011-12-16
    • 1970-01-01
    • 2016-12-16
    • 1970-01-01
    相关资源
    最近更新 更多