2013-01-01 51 views
3

我有我想要寫一個YAML文件中,有兩個文件兩個Python字典YAML文件:Python字典到使用PyYaml

definitions = {"one" : 1, "two" : 2, "three" : 3} 
actions = {"run" : "yes", "print" : "no", "report" : "maybe"} 

YAML的文件應該是這樣:

--- !define 
one: 1 
two: 2 
three: 3 

-- !action 
run: yes 
print: no 
report: maybe 
... 

使用PyYaml我沒有找到明確的方法來做到這一點。我確信有一個簡單的方法,但是深入PyYaml文檔,只會讓我感到困惑。我需要自卸車,發射器還是什麼?每種類型的輸出產生哪種類型的輸出? Yaml文本? yaml節點? YAMLObject?無論如何,我會很感激任何澄清。


按照下面unutbu的答案,這裏是最簡潔的版本,我能想出:

DeriveYAMLObjectWithTag是創建一個新類的功能,從YAMLObject衍生與所需的標籤:

def DeriveYAMLObjectWithTag(tag): 
    def init_DeriveYAMLObjectWithTag(self, **kwargs): 
     """ __init__ for the new class """ 
     self.__dict__.update(kwargs) 

    new_class = type('YAMLObjectWithTag_'+tag, 
        (yaml.YAMLObject,), 
        {'yaml_tag' : '!{n}'.format(n = tag), 
        '__init__' : init_DeriveYAMLObjectWithTag}) 
    return new_class 

這裏是如何使用DeriveYAMLObjectWithTag獲得所需要的YAML:

definitions = {"one" : 1, "two" : 2, "three" : 3, "four" : 4} 
actions = {"run" : "yes", "print" : "no", "report" : "maybe"} 
namespace = [DeriveYAMLObjectWithTag('define')(**definitions), 
      DeriveYAMLObjectWithTag('action')(**actions)] 

text = yaml.dump_all(namespace, 
        default_flow_style = False, 
        explicit_start = True) 

感謝所有回答者。我似乎在PyYaml中缺少功能,而這是克服它的最優雅的方法。

回答

1

如何:

class Bunch(yaml.YAMLObject): 
    yaml_tag = u'!Bunch' 
    def __init__(self, **kwargs): 
     self.__dict__.update(kwargs) 
    def __repr__(self): 
     return '{c}({a})'.format(
      c = self.__class__.__name__, 
      a = ', '.join(
       ['='.join(map(str,item)) for item in self.__dict__.items()])) 
tag_names = ['define', 'action'] 
namespace = {} 
for name in tag_names: 
    namespace[name] = type(name, (Bunch,), {'yaml_tag':u'!{n}'.format(n = name)}) 

definitions = {"one" : 1, "two" : 2, "three" : 3} 
actions = {"run" : "yes", "print" : "no", "report" : "maybe"} 
text = yaml.dump_all([namespace['define'](**definitions), 
         namespace['action'](**actions)], 
        default_flow_style = False, 
        explicit_start = True) 
print(text) 

這將產生

--- !define 
one: 1 
three: 3 
two: 2 
--- !action 
print: 'no' 
report: maybe 
run: 'yes' 

而到了YAML回加載到Python對象:

for item in yaml.load_all(text): 
    print(item) 
    # define(one=1, three=3, two=2) 
    # action(print=no, report=maybe, run=yes) 

YAMLObject的子類被用來創建application-specific tags.

+0

@favoretti:的確是將輸出分割爲文檔的explicit_start = True。 explicit_start在PyYAMLDocumentation中完全沒有記錄,僅在一個示例中提到。 –

+0

爲每個特定標籤聲明一個類的想法是有效的,但是對於有很多這種標籤的大型項目不會擴展。我使用PyYaml越多,我意識到它是多麼的跛腳。 –

+0

我已經添加了一些代碼來顯示如何以編程方式定義類。 – unutbu

7

嗯,我還在尋找到自動評論(無法找到該馬上的文檔),但這應該做的伎倆:

import yaml 

definitions = {"one" : 1, "two" : 2, "three" : 3} 
actions = {"run" : "yes", "print" : "no", "report" : "maybe"} 

output = yaml.dump(actions, default_flow_style=False, explicit_start=True) 
output += yaml.dump(definitions, default_flow_style=False, explicit_start=True) 

print output 

一個謹慎的詞,字典是無序的,所以無法保證您生成的YAML的順序。如果你想在房子裏訂購 - 看看OrderedDict