小さなCLIユーティリティでTinyDBを使用して個人用の下書きを管理しています。データベースには、各ドラフトのメタデータが格納されます。ファイルを人間が編集できるようにする必要があります(手動で詳細を追加できるようにするため)、この理由から、JSONをフォーマットとしてYAMLを使用したいと思います。TinyDBでYAMLストレージを使用すると予期しない動作が発生する
TinyDBドキュメントに示されているように、私はYamlStorage
クラスのサブクラスstorages.Storage
を実装:insert_multiple
を使用して、同時に一つだけの要素または複数の要素を挿入するとき
class TestYamlStorage(Storage):
"""
Store the data in a YAML file.
Written following the example at http://tinydb.readthedocs.io/en/latest/extend.html#write-a-custom-storage
"""
def __init__(self, filename): # (1)
super().__init__()
self.filename = filename
touch(filename)
def read(self):
with open(self.filename) as handle:
try:
data = yaml.load(handle.read())
return data
except yaml.YAMLError:
return None # (3)
def write(self, data):
print('writing data: {}'.format(data))
with open(self.filename, 'w') as handle:
yaml.dump(data, handle)
def close(self): # (4)
pass
すべてが正常に動作:
db = TinyDB('db.yaml', storage=TestYamlStorage)
dicts = [
dict(name='Homer', age=38),
dict(name='Marge', age=34),
dict(name='Bart', age=10)
]
# this works as expected
db.insert_multiple(dicts)
結果はdb.yaml
:
_default:
1: {age: 38, name: Homer}
2: {age: 34, name: Marge}
3: {age: 10, name: Bart}
insert
で要素を複数回挿入するときしかし、得られたYAMLファイルが異なる:
db = TinyDB('db.yaml', storage=TestYamlStorage)
db.insert(dict(name='Homer', age=38))
db.insert(dict(name='Bart', age=10))
db.yaml
:
_default:
1: !!python/object/new:tinydb.database.Element
dictitems: {age: 38, name: Homer}
state: {eid: 1}
2: {age: 10, name: Bart}
この形式のデータは、(離れメシエを見てから)であると思われますyaml.safe_load
(db.all()
を呼び出すと[]
と返されます)と互換性がありません。私の解釈は、YAMLのシリアル化プロセスは何らかの形で「あまりにも熱心」である、つまりElement
インスタンスが基礎データの代わりにdb.yaml
に書き込まれるということです。
私のコードに何か問題がありますか?私は別のYAMLモジュール(ruamel.yaml)を使ってPyYAMLオプションを試してみました。そして、違いなく、デフォルトのJSONStorageから2番目のYamlStorageクラスを作成しました。
バージョン情報:Python 3.4.3、TinyDB 3.2.0、PyYAML 3.11。私は、すべての輸入品と実行可能なMWEを投稿したhere。
編集
@ Anthonのの提案の後、私はすぐにファイルにダンプする前にsys.stdout
にYAML出力を印刷してみました。この場合も問題が再現されます。 notebookを参照してください。
私はあなたの提案を試みたが、残念ながら違いを確認していないようです。関連性がある場合、 'yaml.dump'を呼び出す前の' print(type(data)) 'は' 'を返します。 –
fndari
私はむしろ 'stream = sys.stdout'でYAMLのダンプを行いたいので、YAMLが何を得ていると思うかを知ることができます。 – Anthon
私は質問にノートブックへのリンクを 'sys.stdout'へのダンプとともに追加しました。 – fndari