2013-08-22 168 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的增強版本的作者。