I am trying to output and then to parse back from YAML the following
import numpy as np
class MyClass(object):
YAMLTag = '!MyClass'
def __init__(self, name, times, zeros):
self.name = name
self._T = np.array(times)
self._zeros = np.array(zeros)
The YAML file looks like
!MyClass:
name: InstanceId
times: [0.0, 0.25, 0.5, 1.0, 2.0, 5.0, 10.0]
zeros: [0.03, 0.03, 0.04, 0.03, 0.03, 0.02, 0.03]
To write, I have added to the class two methods
def toDict(self):
return {'name' : self.name,
'times' : [float(t) for t in self._T],
'zeros' : [float(t) for t in self._zeros]}
@staticmethod
def ToYAML(dumper, data):
return dumper.represent_dict({data.YAMLTag : data.toDict()})
and to read, the method
@staticmethod
def FromYAML(loader, node):
nodeMap = loader.construct_mapping(node)
return MyClass(name = nodeMap['name'],
times = nodeMap['times'],
zeros = nodeMap['zeros'])
and following YAML Documentation, I added the following snippet in the same Python file myClass.py
:
import yaml
yaml.add_constructor(MyClass.YAMLTag, MyClass.FromYAML)
yaml.add_representer(MyClass, MyClass.ToYAML)
Now, the writing seems to work ok, but reading the YAML, the code
loader.construct_mapping(node)
seems to return the dictionary with empty data:
{'zeros': [], 'name': 'InstanceId', 'times': []}
How should I fix the reader to be able to do this properly? Or perhaps I am not writing something out right? I spent a long time looking at PyYAML documentation and debugging through how the package is implemented but cannot figure out a way to parse out a complicated structure, and the only example I seemed to find has a 1-line class which parses out easily.
Related: YAML parsing and Python
UPDATE
Manually parsing the node as follows worked:
name, times, zeros = None, None, None
for key, value in node.value:
elementName = loader.construct_scalar(key)
if elementName == 'name':
name = loader.construct_scalar(value)
elif elementName == 'times':
times = loader.construct_sequence(value)
elif elementName == 'zeros':
zeros = loader.construct_sequence(value)
else:
raise ValueError('Unexpected YAML key %s' % elementName)
But the question still stands, is there a non-manual way to do this?
Instead of
nodeMap = loader.construct_mapping(node)
try this:
nodeMap = loader.construct_mapping(node, deep=True)
Also, you have a little mistake in your YAML file:
!MyClass:
The colon at the end does not belong there.