今回は、
PyYAML
PyYAMLは、
Webサイト | http:// |
---|---|
ドキュメント | http:// PyYAMLDocumentation |
ダウンロード | http:// |
バージョン | 3. |
作者 | Kirill Simonov |
インストール
インストールは、
$ wget http://pyyaml.org/download/pyyaml/PyYAML-3.05.tar.gz $ tar xzf PyYAML-3.05.tar.gz $ cd PyYAML-3.05/ $ sudo python setup.py install
使い方
PyYAMLの使い方はリスト2のようになります。日本語を含む場合は必ずUnicodeにデコードしなければならない点に注意してください。詳細はリファレンスマニュアルを参照してください。
import yaml
## YAMLドキュメントを読み込む
string = open('example.yaml').read()
string = string.decode('utf8') # 日本語を含む場合はデコードする
data = yaml.load(string)
print repr(data)
## または
## data = yaml.load(open('example.yaml'))
## print repr(data)
## YAMLストリームを読み込む
for data in yaml.load_all(string):
print repr(data)
## または
## for data in yaml.load_all(open('example.yaml')):
## print repr(data)
## 任意のデータをYAML文字列に変換する
## (allow_unicode=Trueを指定すると、日本語がエンコードされない)
data = [ {'x':10, 'y':20}, {'x':15, 'y':25} ]
print yaml.dump(data, encoding='utf8', allow_unicode=True)
## またはファイルに出力する場合:
## f = open('dump.yaml', 'w')
## yaml.dump(data, f, encoding='utf8', allow_unicode=True)
またYAMLでは任意のオブジェクトを変換/
- yaml.
safe_ load() - yaml.
load()と同じですが、 「!!python/ object:__ main__.Hello」 のようなタグがあるとエラーになります。 - yaml.
safe_ dump() - yaml.
dump()と同じですが、 listやmapやスカラー以外のオブジェクトがあるとエラーになります。
これらを使うと、
タグを変更する
yaml.
これを回避するには、
- yaml.
add_ representer(klass, func) - オブジェクトをノード
(yaml. nodes. Node) に変換する関数を登録します。 - yaml.
add_ constructor(ytag, func) - ノード
(yaml. nodes. Node) からオブジェクトを復元する関数を登録します。
# -*- coding: utf-8 -*-
import yaml
## クラスに対応するタグを登録するユーティリティ
def yaml_register_class(klass, ytag):
suffix = '%s.%s' % (klass.__module__, klass.__name__)
def representer(dumper, instance):
node = dumper.represent_mapping(ytag, instance.__dict__)
return node
def constructor(loader, node):
instance = loader.construct_python_object(suffix, node)
return instance
yaml.add_representer(klass, representer)
yaml.add_constructor(ytag, constructor)
## または
#suffix = '%s.%s' % (klass.__module__, klass.__name__)
#f1 = lambda dumper, obj: dumper.represent_mapping(ytag, obj.__dict__)
#f2 = lambda loader, node: loader.construct_python_object(suffix, node)
#yaml.add_representer(klass, f1)
#yaml.add_constructor(ytag, f2)
## クラス定義
class Color(object):
def __init__(self, r, g, b):
self.r = r
self.g = g
self.b = b
## クラスに対応するタグを登録する
yaml_register_class(Color, '!color')
## 実行例
c = Color(255, 128, 0)
print yaml.dump(c) #=> !color {b: 0, g: 128, r: 255}
s = '!color {b: 0, g: 128, r: 255}'
c = yaml.load(s)
print c #=> <__main__.Color object at 0x5be510>
print c.__dict__ #=> {'r': 255, 'b': 0, 'g': 128}
.--------------------
またオブジェクトをマッピング以外のデータで表現することもできます。リスト4は、
# -*- coding: utf-8 -*-
import yaml
## クラス定義
class Color(object):
def __init__(self, r, g, b):
self.r = r
self.g = g
self.b = b
## Colorインスタンスをノードに変換する関数
def color_representer(dumper, color):
## 文字列に変換する場合
s = '#%02x%02x%02x' % (color.r, color.g, color.b)
node = dumper.represent_scalar(u'!color', s)
return node
## シーケンスに変換する場合
#L = [color.r, color.g, color.b]
#node = dumper.represent_mapping(u'!color', L)
#return node
yaml.add_representer(Color, color_representer)
## 実行例
print yaml.dump(Color(255, 0, 0))
#=> !color '#ff0000' (スカラーに変換した場合)
#=> !color [255, 0, 0] (シーケンスに変換した場合)
## ノードからColorインスタンスを復元する関数
def color_constructor(loader, node):
## 文字列を表すノードから変換する場合
s = loader.construct_scalar(node)
import re
pat = '#' + '([a-fA-F0-9][a-fA-F0-9])' * 3
m = re.match(pat, s)
if not m:
msg = '%s: invalid color' % s
raise yaml.constructor.ConstructorError(msg)
r, g, b = m.groups()
return Color(int(r, 16), int(g, 16), int(b, 16))
## シーケンスを表すノードから変換する場合
#L = loader.construct_sequence(node)
#return Color(L[0], L[1], L[2])
yaml.add_constructor(u'!color', color_constructor)
## 実行例(文字列から変換した場合)
color = yaml.load("!color '#FF8000'")
print "color: r=%s, g=%s, b=%s" % (color.r, color.g, color.b)
#=> color: r=255, g=128, b=0
## 実行例(シーケンスから変換した場合)
#color = yaml.load('!color [255, 128, 0]')
#print "color: r=%s, g=%s, b=%s" % (color.r, color.g, color.b)
# #=> color: r=255, g=128, b=0
日本語の扱い
yaml.
yaml.
その他
Pythonのlistオブジェクトやdictオブジェクトは、
- ほかのコンテナを含んでいればブロックスタイル
- ほかのコンテナを含んでいなければフロースタイル
フロースタイルを使わずすべてをブロックスタイルにしたい場合は、
## point1とpoint2はコンテナを含んでいないのでフロースタイル、
## pointsはコンテナを含んでいるのでブロックスタイルになる。
point1 = {'x':10, 'y':20}
point2 = {'x':15, 'y':25}
points = [ point1, point2 ]
print yaml.dump(points),
## 実行結果:
## - {x: 10, y: 20}
## - {x: 15, y: 25}
## default_flow_style=Falseを指定すると、すべてブロックスタイルになる。
print yaml.dump(points, default_flow_style=False),
## 実行結果:
## - x: 10
## y: 20
## - x: 15
## y: 25
LibYAML for Python
LibYAMLは、
Webサイト | http:// |
---|---|
ドキュメント | http:// |
ダウンロード | http:// |
バージョン | 0. |
作者 | Kirill Simonov |
インストール
LibYAMLのインストールは、
$ wget http://pyyaml.org/download/libyaml/yaml-0.0.1.tar.gz $ tar xzf yaml-0.0.1.tar.gz $ cd yaml-0.0.1/ $ ./configure $ make $ sudo make install
またLibYAMLをPythonから使うには、
インストールには、
$ wget http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/Pyrex-0.9.6.4.tar.gz $ tar xzf Pyrex-0.9.6.4.tar.gz $ cd Pyrex-0.9.6.4/ $ sudo python setup.py install $ cd .. $ wget http://pyyaml.org/download/pyyaml/PyYAML-3.05.tar.gz $ tar xzf PyYAML-3.05.tar.gz $ cd PyYAML-3.05/ $ sudo python setup_with_libyaml.py install
使い方
LibYAMLをPythonから使う方法は、
- yaml.
load()において、 引数に 「Loader=CLoader」 を指定する - yaml.
dump()において、 引数に 「Dumper=CDumper」 を指定する
つまりPyYAML標準のLoaderクラスとDumperクラスの代わりに、
リスト8は使い方のサンプルです。ここではLibYAML'がインストールされていてもいなくても動作するようにしています。
# -*- coding: utf-8 -*-
import yaml
try:
## LibYAMLがインストールされている場合はそれを使う
from yaml import CLoader as Loader
from yaml import CDumper as Dumper
except ImportError:
## インストールされていない場合はPyYAMLを使う
from yaml import Loader, Dumper
## YAMLドキュメントを読み込む
import sys
string = open('example.yaml').read()
string = string.decode('utf8') # 日本語を含む場合はデコードする
data = yaml.load(string, Loader=Loader)
## または
## data = yaml.load(open('example.yaml'), Loader=Loader)
## 任意のデータをYAML文字列に変換する
data = [ {'x':10, 'y':20}, {'x':15, 'y':25} ]
print yaml.dump(data, Dumper=Dumper)
## またはファイルに出力する場合:
## f = open('dump.yaml', 'w')
## print yaml.dump(data, f, Dumper=Dumper)
日本語の扱い
日本語の扱いについては、
タグを変更する
タグを変更する方法は、
不具合
筆者が試した範囲では、
その他
当然ですが、