Ich verwende TinyDB für ein kleines CLI-Dienstprogramm, um persönliche Dokumententwürfe zu verwalten. Die Datenbank speichert Metadaten für jeden Entwurf; Die Datei sollte manuell editierbar sein (damit ich manuell Details hinzufügen kann), und aus diesem Grund möchte ich YAML über JSON als Format verwenden.Unerwartetes Verhalten bei Verwendung von YAML Storage mit TinyDB
ich implementiert eine YamlStorage
Klasse Subklassifizieren storages.Storage
wie in den TinyDB docs angegeben:
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
Alles funktioniert gut, wenn nur ein Element eingesetzt wird, oder mehrere Elemente gleichzeitig insert_multiple
mit:
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)
Die resultierende db.yaml
:
_default:
1: {age: 38, name: Homer}
2: {age: 34, name: Marge}
3: {age: 10, name: Bart}
Wenn jedoch Elemente mehrere Male mit insert
Einsetzen ist die resultierende YAML-Datei anders:
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}
Die Daten in diesem Format (abgesehen von der Suche messier) scheint zu sein, nicht kompatibel mit yaml.safe_load
(Aufruf db.all()
gibt []
zurück). Meine Interpretation ist, dass der YAML-Serialisierungsprozess in gewisser Weise "übereifrig" ist, d. H. Dass die Element
-Instanz anstelle der zugrunde liegenden Daten in db.yaml
geschrieben wird.
Ist mit meinem Code etwas nicht in Ordnung? Ich habe versucht, mit PyYAML-Optionen zu experimentieren, ein anderes YAML-Modul (ruamel.yaml) zu verwenden und eine zweite YamlStorage-Klasse zu erstellen, die von der Standard-JSONStorage kopiert, aber ohne Unterschied.
Versionsinfo: Python 3.4.3, TinyDB 3.2.0, PyYAML 3.11. Ich habe ein lauffähiges MWE mit allen Importen here gepostet.
bearbeiten
Nach @ Anthon Vorschlag, ich sys.stdout
sofort den YAML Ausgangsdruck versucht, bevor eine Datei Dumping. Das Problem wird auch in diesem Fall reproduziert. Siehe notebook.
ich Ihren Vorschlag versucht, aber leider scheint es nicht einen Unterschied zu machen. Wenn es relevant sein kann, gibt 'print (type (data))' zurück, bevor der Aufruf von 'yaml.dump'' 'zurückgibt. –
fndari
Ich würde lieber einen YAML-Dump mit 'stream = sys.stdout' machen, damit Sie sehen können, was YAML denkt. – Anthon
Ich habe einen Link zu einem Notebook zu meiner Frage mit dem Dump zu 'sys.stdout' hinzugefügt. – fndari