pythonでyamlを使ってみる


自作ソフトで今まで設定ファイルにConfigParserを使っていたのですが、

ふと思い立ってPyYamlを使ってみました。


yamlのよいところ




  1. yaml.load一発で読み込める

    (ConfigParserは項目毎に型を指定する必要がある)



  2. yaml.dump一発で書き込める

    (ConfigParserは項目毎に型を指定する必要がある)



  3. 独自の型を追加できる。

    (ConfigParserでも出来るが、PyYamlは独自型の追加方法が系統だっている)


1. yaml.load一発で読み込める



もちろん、堅牢性を考えると、読み込んだデータの型が正しいかチェックが必要ですが、

そんなに複雑なコードは要りません。

from __future__ import with_statement, division, print_function
import yaml

#型チェック関数
#その型に変換できたら、変換した値を
#変換できなかったらTypeError
def ensure_int(x):
    try:
        return int(x)
    except (ValueError, TypeError):
        raise TypeError

def ensure_str(x):
    if isinstance(x, basestring):
        return unicode(x)
    else:
        raise TypeError
        
def ensure_strlist(x):
    if isinstance(x, list):
        x1 = list(x)
        return [ensure_str(i) for i in x1]
    else:
        raise TypeError
    
types = dict(
    number=ensure_int,
    dirname=ensure_str,
    extpattern = ensure_strlist,
)

ss = """
number : "xyz"
dirname : "D:/Owner/My Documents/My Picture"
extpattern : ["*.png", "*.jpg"]
"""

d = yaml.load(ss)
for name, func in types.iteritems():
    try:
        func(d[name])
    except TypeError:
        print(name, "の型が違う")
 


また、簡単なプログラムなら、異常終了するに任せてもよいでしょう。

2. yaml.dump一発で書き込める



書き込む時は型チェックは普通要らないので、(型が違っていたら、それはバグ)


一々型を指定するのは冗長です。

3.独自の型を追加できる



当然ながら、対応したプログラムでしか読み込めなくなりますが。

#encoding:utf-8
from __future__ import with_statement, division, print_function
import wx
import yaml
Dumper = yaml.SafeDumper
Loader = yaml.SafeLoader

## wxColourインスタンスをノードに変換する関数
def color_representer(dumper, color):
    L = [color.Red(), color.Green(), color.Blue()]
    node = dumper.represent_sequence(u'!wxColour', L)
    return node
Dumper.add_representer(wx.Colour, color_representer)

## ノードからColorインスタンスを復元する関数
def color_constructor(loader, node):
    L = loader.construct_sequence(node)
    return wx.Colour(L[0], L[1], L[2])
Loader.add_constructor(u'!wxColour', color_constructor)

s = "!wxColour [255, 128, 64]"
color = yaml.load(s, Loader=Loader)
print(color)

s1 = yaml.dump(s, Dumper=Dumper)
print(s1)