2013-08-22 144 views
3

我有这样的嵌套字典类,其实例我需要转储到YAMLPYAML投掷表示错误

class NestedDict(dict): 
    """Implementation of perl's autovivification feature.""" 
    def __getitem__(self, item): 
     try: 
      return dict.__getitem__(self, item) 
     except KeyError: 
      value = self[item] = type(self)() 
      return value 

倾销这本字典:

pyaml.dump(nesteddict) 

我得到这个错误(仅摘录的整个邮件对象发布):

"RepresenterError: cannot represent an object: {'a1401': 'ts755', 'ts64': {'topic': {'a1561': 'Process Control'}}, 'a1450': 'ts107', 'a1609': 'ts341', 'a1400': 'ts753', ......

那么如何在YAML中整齐地表示这个呢?我读过PyYAML支持嵌套递归结构。

+0

您可以粘贴您尝试创建的对象(基本上是输入和输出)的代码。尝试使用翻车机。 – Vivek

回答

2

YAML确实可以支持嵌套的递归结构:

import ruamel.yaml 

data = [1, 3] 
data.append(data) 

print ruamel.yaml.dump(data) 

会给你YAML用锚(&id001)和参考(*id001):

&id001 
- 1 
- 3 
- *id001 

和你一个dict的简单衍生物至少与ruamel.yaml没有问题一起¹:

import ruamel.yaml 

class NestedDict(dict): 
    """Implementation of perl's autovivification feature.""" 
    def __getitem__(self, item): 
     try: 
      return dict.__getitem__(self, item) 
     except KeyError: 
      value = self[item] = type(self)() 
      return value 

data = NestedDict(a=1, b=2) 
data['c'] = data 

print ruamel.yaml.dump(data) 

这给了你:

&id001 !!python/object/new:__main__.NestedDict 
dictitems: 
    a: 1 
    b: 2 
    c: *id001 

如果你需要一个更复杂的表示,例如滤除一些 字典值,你必须告诉ruamel.yaml如何表示你的对象。 要告诉它,NestedDict有一个代理人,您可以将其设为ruamel.yaml.YAMLObject的子类,提供类属性yaml_tag = "!NestedDict"并实现__repr__();或者你可以提供一个明确的代表。

后者是内部使用的和IMO稍微容易实现的,因为您可以通过返回字典表示(即顶级键 - 值对)对象来捎带回字典代码。

def nested_dict_representer(dumper, node): 
    return dumper.represent_mapping("!NestedDict", xyz) 

其中xyz是您的对象的一些键值对表示。


¹免责声明:我是包,这是PyYAML的增强版本的作者。