簡體   English   中英

使用Python和ruamel.yaml中的引用序列化YAML

[英]Serialize YAML with references in Python and ruamel.yaml

我有一個帶有引用的yaml文件,想要讀取該文件並創建對象。 YAML-File的內容由“消息”類和“信號”類組成。 消息可以包含對選定信號的引用列表。 有什么好的方法? 我目前將使用from_yaml方法並對YAML-line解碼。 我已經嘗試過使用Signal和Message這兩個類,但是解析器似乎期望其他語法或其他語法。

ruamel.yaml.parser.ParserError:在“ input4.yaml”第18行第6列中解析塊集合時,在“ input4.yaml”第18行第17列中未找到預期的“-”指示符

什么是讀取和解碼文件的好方法。 一種可能是忽略引用,用“ from_yaml”解析失敗,然后在第二步中手動將引用放在一起,但是也許有更好的方法。

附加了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 

我的phyton程序看起來像

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")

您的YAML有兩個問題:

1)您應該適當縮進所有內容:第18行和第19行需要縮進更多的兩個空格,以便該序列算作鍵Signals值;而出於相同的原因,第25-27行也需要縮進4個空格。

2)您可以編寫!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 . The effect is the same: you get an anchor for a " type". Ie the type information is "included" in the anchor type". Ie the type information is "included" in the anchor Signal1`中,並且不應在別名中重復。

以下input4.yaml隨程序input4.yaml加載,沒有錯誤:

# 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

順便說一句,它是Python,而不是Phyton(我在問題中已經對其進行了兩次更新,您應該查看人們對您的帖子所做的編輯,並向他們學習)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM