とあるプログラムのテストコードをpickleを使って表現しようと思ったんだけれども、どうも手書きでデータ構造を生成するのは大変そう。しかたがないのでYAMLにしてみた。

YAMLパーサはモジュールを別途インストールしないといけないの...電池付属のPythonの付属の電池だけでなんとかしたかった...
PythonYAMLパーサとしてはPyYAMLとPySyckが主流(なのか?)みたい。
どちらを使うか

  • PyYAML is the next generation YAML parser and emitter for Python.
  • PySyck PySyck is a Python binding to Syck, a C library for reading and writing YAML in scripting languages.

今回は、PyYAMLを使ってみることにした。まずはインストール。


$ tar zxvf PyYAML-3.09.tar.gz
$ cd PyYAML-3.09
$ python setup.py test
$ sudo python setup.py install
$
やりたいことは、データ構造をそのままファイルへ入出力すること。

$ python
>>> import yaml
>>> x = {'Name':'foo','email':['foo@example.com','bar@example.com']}
>>> fp = open('test.dat','w')
>>> yaml.dump(x,fp)
>>> fp.close()
>>> ^D
$
これで、'test.dat'にデータ構造が出力されているはず...

$ cat test.dat
Name: foo
email: [foo@example.com, bar@example.com]
$
成功!
こんどは読み込んでみる。

$ python
>>> import yaml
>>> fp = open('test.dat','r')
>>> y = yaml.load(fp)
>>> fp.close()
>>> print y
{'Name': 'foo', 'email': ['foo@example.com', 'bar@example.com']}
>>> ^D
$
YAML形式で保存されたデータを無事に読み込んで、データ構造が再現できた。

続いて、load_all()とdump_all()で複数レコードのデータを扱ってみる。


$ python
>>> import yaml
>>> fp = open('test.dat','w')
>>> x = [
... {'Name':'foo','email':['foo@example.com','foo00@example.com']},
... {'Name':'bar','email':['bar@example.com','bar00@example.com']},
... {'Name':'baz','email':['baz@example.com','baz00@example.com']},
... ]
>>> yaml.dump_all(x,fp)
>>> fp.close()
>>> ^D
dump_all()で保存したデータ構造の内容を確認してみる。

$ cat test.dat
Name: foo
email: [foo@example.com, foo00@example.com]

    • -

Name: bar
email: [bar@example.com, bar00@example.com]

    • -

Name: baz
email: [baz@example.com, baz00@example.com]
$

load_all()でロードしてみる。
load_all()はgeneratorオブジェクトを返してくれるので、こんな使い方ができる。

$ python
>>> import yaml
>>> fp = open('test.dat','r')
>>> x = yaml.load_all(fp)
>>> print x.next()
{'Name': 'foo', 'email': ['foo@example.com', 'foo00@example.com']}
>>> print x.next()
{'Name': 'bar', 'email': ['bar@example.com', 'bar00@example.com']}
>>> print x.next()
{'Name': 'baz', 'email': ['baz@example.com', 'baz00@example.com']}
>>> print x.next()
Traceback (most recent call last):
File "", line 1, in
StopIteration
>>> fp.close()
>>> ^D
もちろん for ループでも利用できる。

$ python
>>> import yaml
>>> fp = open('test.dat','r')
>>> x = yaml.load_all(fp)
>>> for line in x:
... print line
...
{'Name': 'foo', 'email': ['foo@example.com', 'foo00@example.com']}
{'Name': 'bar', 'email': ['bar@example.com', 'bar00@example.com']}
{'Name': 'baz', 'email': ['baz@example.com', 'baz00@example.com']}
>>> fp.close()
>>> ^D