読者です 読者をやめる 読者になる 読者になる

OrderedDictをYAMLに変換する

Python

Python 3.1/2.7のcollections.OrderedDictodictYAMLに変換したい時、

import yaml

o = OrderedDict()
o['spam'] = 1
o['egg'] = 2
o['ham'] = 3

print yaml.dump(o, default_flow_style=False)

で期待する結果は、

!!python/object/apply:collections.OrderedDict
- - - spam
    - 1
  - - egg
    - 2
  - - ham
    - 3

ではなく、

spam: 1
egg: 2
ham: 3

だと思う。

それには yaml.add_representer でOrderedDictの変換方法を定義してやればよい。逆に、YAMLのmappingを常にOrderedDictとして扱いたい場合には、yaml.add_constructor で変換方法を指定する。

以下はそのサンプルコード。OrderDictとpairのリストを相互に変換していることろがポイント。

import yaml

try:
    from collections import OrderedDict
except ImportError:
    from odict import odict as OrderedDict

def represent_odict(dumper, instance):
     return dumper.represent_mapping(u'tag:yaml.org,2002:map', instance.items())

yaml.add_representer(OrderedDict, represent_odict)

def construct_odict(loader, node):
    return OrderedDict(loader.construct_pairs(node))

yaml.add_constructor(u'tag:yaml.org,2002:map', construct_odict)

if __name__ == '__main__':
    o = OrderedDict()
    o['spam'] = 1
    o['egg'] = 2
    o['ham'] = 3

    result = yaml.dump(o, default_flow_style=False)
    print result

    result = yaml.load(result)
    for key, value in result.items():
        print key, value

出力結果は以下のようになる。

spam: 1
egg: 2
ham: 3

spam 1
egg 2
ham 3

参考ページ。