我正在使用 TinyDB 作为一个小型 CLI 实用程序来管理个人文档草稿。数据库存储每个草稿的元数据;该文件应该是人工可编辑的(以便我可以手动添加详细信息),因此我想使用 YAML over JSON 作为格式。
我实现了TinyDB 文档中所示的YamlStorage
类子类化:storages.Storage
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
使用以下方法仅插入一个元素或同时插入多个元素时一切正常insert_multiple
:
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 复制创建第二个 YamlStorage 类,但没有任何区别。
版本信息:Python 3.4.3、TinyDB 3.2.0、PyYAML 3.11。我在这里发布了一个包含所有导入的可运行 MWE 。
编辑
在@Anthon 的建议之后,我尝试sys.stdout
在转储到文件之前立即打印 YAML 输出。在这种情况下也重现了该问题。见笔记本。