Gibt es eine Möglichkeit, ein Objekt mit PyYAML construct_mapping zu erstellen, nachdem alle Knoten vollständig geladen wurden?
Ich versuche, eine Yaml-Sequenz in Python zu erstellen, die ein benutzerdefiniertes Python-Objekt erstellt. Das Objekt muss mit Dikten und Listen konstruiert werden, die anschließend dekonstruiert werden__init__
. Es scheint jedoch, dass die Funktion construct_mapping nicht den gesamten Baum von eingebetteten Sequenzen (Listen) und Dikten erstellt.
Folgendes berücksichtigen:
import yaml
class Foo(object):
def __init__(self, s, l=None, d=None):
self.s = s
self.l = l
self.d = d
def foo_constructor(loader, node):
values = loader.construct_mapping(node)
s = values["s"]
d = values["d"]
l = values["l"]
return Foo(s, d, l)
yaml.add_constructor(u'!Foo', foo_constructor)
f = yaml.load('''
--- !Foo
s: 1
l: [1, 2]
d: {try: this}''')
print(f)
# prints: 'Foo(1, {'try': 'this'}, [1, 2])'
Das funktioniert gut, weilf
hält die Verweise auf diel
undd
Objekte, die tatsächlich mit Daten gefüllt sindnach dem dasFoo
Objekt wird erstellt.
Lass uns etwas komplizierteres machen:
class Foo(object):
def __init__(self, s, l=None, d=None):
self.s = s
# assume two-value list for l
self.l1, self.l2 = l
self.d = d
Jetzt erhalten wir den folgenden Fehler
Traceback (most recent call last):
File "test.py", line 27, in <module>
d: {try: this}''')
File "/opt/homebrew/lib/python2.7/site-packages/yaml/__init__.py", line 71, in load
return loader.get_single_data()
File "/opt/homebrew/lib/python2.7/site-packages/yaml/constructor.py", line 39, in get_single_data
return self.construct_document(node)
File "/opt/homebrew/lib/python2.7/site-packages/yaml/constructor.py", line 43, in construct_document
data = self.construct_object(node)
File "/opt/homebrew/lib/python2.7/site-packages/yaml/constructor.py", line 88, in construct_object
data = constructor(self, node)
File "test.py", line 19, in foo_constructor
return Foo(s, d, l)
File "test.py", line 7, in __init__
self.l1, self.l2 = l
ValueError: need more than 0 values to unpack
Dies liegt daran, dass der yaml-Konstruktor mit der äußeren Ebene des Verschachtelns vor und des Konstruierens des Objekts beginnt, bevor alle Knoten fertig sind. Gibt es eine Möglichkeit, die Reihenfolge umzukehren und zuerst mit tief eingebetteten (z. B. verschachtelten) Objekten zu beginnen? Alternativ gibt es eine Möglichkeit, den Bau zumindest zum Laufen zu bringennach dem die Objekte des Knotens wurden geladen?