【发布时间】:2016-05-17 15:33:42
【问题描述】:
我正在使用 TinyDB 作为一个小型 CLI 实用程序来管理个人文档草稿。数据库存储每个草稿的元数据;该文件应该是人工可编辑的(以便我可以手动添加详细信息),因此我想使用 YAML over JSON 作为格式。
我实现了 YamlStorage 类的子类化 storages.Storage,如 TinyDB 文档中所述:
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,其中包含所有导入 here。
编辑
在@Anthon 的建议之后,我尝试在转储到文件之前立即将 YAML 输出打印到 sys.stdout。在这种情况下也重现了该问题。见notebook。
【问题讨论】: