I have a yaml
file with references and want to read the file and create objects. The content of the YAML-File
consists of class "Message" and class "Signal". A Message can hold a list of references to selected Signals. What would be a good approach? I currently would use the from_yaml
method and decode the YAML-line
. I already tried with two classes Signal and Message but it seems that the parser expects either another syntax or something else.
ruamel.yaml.parser.ParserError: while parsing a block collection in "input4.yaml", line 18, column 6 did not find expected '-' indicator in "input4.yaml", line 18, column 17
What could be a good approach for reading and decoding the file. One could be to ignore the reference, parse the fail with "from_yaml" and in a second step to put the references together manually but maybe there is a better way.
Attached the yaml-File
# input4.yaml - !Signal &Signal1 Name: AO1 Length: 3 - !Signal &Signal2 Name: AO2 Length: 4 - !Signal &Signal3 Name: AO3 Length: 4 - !Message Name: Message1 Value: 122 Signals: - !Signal *Signal1 - !Signal *Signal2 - !Message Name: Message2 Value: 123 Signals: - !Signal *Signal1 - !Signal *Signal2 - !Signal *Signal3
My phyton program looks like
import ruamel.yaml
class Signal:
def __init__(self, name=None, Length=None):
self.name = name
self.Length = Length
@classmethod
def from_yaml(cls, constructor, node):
for m in constructor.construct_yaml_map(node):
pass
return cls(m['Name'], m['Length'])
def __repr__(self):
return 'Signal(name={.name}, Length={.Length})'.format(self, self)
class Message:
def __init__(self, name=None, DLC=None, object=None, signals=None):
self.name = name
self.dlc = DLC
self.signals = [] if signals is None else signals
@classmethod
def from_yaml(cls, constructor, node):
for m in constructor.construct_yaml_map(node):
pass
if 'Name' in m:
name = m['Name']
elif 'name' in m:
name = m['name']
else:
name = None
object = m['object'] if 'object' in m else None
if 'DLC' in m:
dlc = m['DLC']
else:
dlc = None
if 'Signals' in m:
signals = m['Signals']
else:
signals = None
return cls(name, dlc, object, signals)
#return cls(name, dlc, object, signals)
def __repr__(self):
return 'Message(name={}, DLC={}, signals{})'.format(
self.name, self.dlc, self.object, '[...]' if self.signals else '[]'
)
yaml = ruamel.yaml.YAML(typ='safe')
yaml.register_class(Message)
yaml.register_class(Signal)
with open('input4.yaml') as fp:
data = yaml.load(fp)
print(len(data))
for m in data:
if isinstance(m, Message):
print("Message: ", m.name)
if Message(m).signals is not None:
for l in m.signals:
if isinstance(l, Signal):
print("Signal: ", l.name)
print("finish")
There are two problems with your YAML:
1) You should properly indent everything: line 18 and 19 need to be indented two spaces more for the sequence to count as value for key Signals
, and lines 25-27 need to be indented 4 spaces more for the same reason.
2) You can write !Signal
&Signal1 , but IMHO it is more clear to write
&Signal1 !Signal . The effect is the same: you get an anchor for a "
. The effect is the same: you get an anchor for a "
!Signal type". Ie the type information is "included" in the anchor
type". Ie the type information is "included" in the anchor
Signal1` and should not be repeated in the alias.
The following input4.yaml
loads with your program without error:
# input4.yaml
- &Signal1 !Signal
Name: AO1
Length: 3
- !Signal &Signal2
Name: AO2
Length: 4
- !Signal &Signal3
Name: AO3
Length: 4
- !Message
Name: Message1
Value: 122
Signals:
- *Signal1
- *Signal2
- !Message
Name: Message2
Value: 123
Signals:
- *Signal1
- *Signal2
- *Signal3
BTW it is Python and not Phyton (which I updated already twice in your questions, you should review edits people make to your posts, and learn from them).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.