簡體   English   中英

讀取 YAML 文件並創建 Python 對象

[英]Read YAML file and create Python objects

我是 Python 新手並嘗試閱讀 YAML 文件。 根據其內容,我想創建 Python 對象。 我正在使用 ruamel-yaml 庫。 就我而言,也許我有 Python 類消息、信號和信號組等(請參閱示例文件)。

我的方法是讀取 YAML 文件,檢查給定關鍵字的每一行並創建相關對象並用數據填充它。 我認為這是“老派”方法,也許有更有效的方法來處理文件。

也許使用函數 register_class/ rep。 創建標簽“from_yaml”但由於鍵被索引它不起作用。

Message1:
Message2:
Message3:

有沒有更專業的方法?

# Yaml Testfile

- ModuleName: myTestModule
- Version: 1.0
- ModuleNumbers: [96,97,98,99]


- Message1:
   Name: AO3_
   DLC: 8
   Signal1:
     Name: Temperature
     Length: 16
   Signal2:
     Name: AnalogOut3
     Length: 16
     SignalGroup1:  #Comment
        Name: app_fcex
        Type: Bitfield
        Signal1:
            Name: drive_ready
            Length: 1
        Signal2:
            Name: error_active
            Length: 1
        Signal3:
            Name: warning_active            
            Length: 1
   Signal3:
     Name: Temperatur 2
     Length: 8
     ValueTable:
        Name: TempStates
        Item0:
           Name: INIT
           Value: 1
        Item1:
           Name: RUN
           Value: 2
        Item2:
           Name: DONE
           Value: 3
        Item3:
           Name: ERROR
           Value: 4
- Message2:
   name: AO2_
   object: RX2
   DLC: 8

我建議您在 YAML 文件中使用標簽,並放棄使用名稱為Item1Item2的鍵(替換為標記對象列表)。

很難看到數據的確切結構,但第一步可能是制作 YAML 文檔(假設在文件input.yaml

- ModuleName: myTestModule
- Version: 1.0
- ModuleNumbers: [96,97,98,99]


- !Message
  Name: AO3_
  DLC: 8
  Signal1:
    Name: Temperature
    Length: 16
  Signal2:
    Name: AnalogOut3
    Length: 16
    SignalGroup1:  #Comment
       Name: app_fcex
       Type: Bitfield
       Signal1:
           Name: drive_ready
           Length: 1
       Signal2:
           Name: error_active
           Length: 1
       Signal3:
           Name: warning_active
           Length: 1
  Signal3:
    Name: Temperatur 2
    Length: 8
    ValueTable:
       Name: TempStates
       items:
       - !Item
         Name: INIT
         Value: 1
       - !Item
         Name: RUN
         Value: 2
       - !Item
         Name: DONE
         Value: 3
       - !Item
         Name: ERROR
         Value: 4
- !Message
  name: AO2_
  object: RX2
  DLC: 8

並加載:

import sys
import ruamel.yaml


class Item:
    def __init__(self, name=None, value=None):
        self.name = name
        self.value = value

    @classmethod
    def from_yaml(cls, constructor, node):
        for m in constructor.construct_yaml_map(node):
            pass
        return cls(m['Name'], m['Value'])

    def __repr__(self):
        return 'Item(name={.name}, value={.value})'.format(self, self)

class Message:
    def __init__(self, name=None, DLC=None, object=None, signals=None):
        self.name = name
        self.dlc = DLC
        self.object = object
        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']
        elif 'Signal1' in m:
            x = 1
            signals = []
            while True:
                name = "Signal{}".format(x)
                try:
                    signals.append(m[name])
                except KeyError:
                    break
                x += 1
        else:
            signals = None
        return cls(name, dlc, object, signals)

    def __repr__(self):
        return 'Message(name={}, DLC={}, object={}, signals{})'.format(
            self.name, self.dlc, self.object, '[...]' if self.signals else '[]',
        )

yaml = ruamel.yaml.YAML(typ='safe')
yaml.register_class(Item)
yaml.register_class(Message)
with open('input.yaml') as fp:
    data = yaml.load(fp)

以上對密鑰可用性進行了一些但有限的檢查(例如規范化!Message Namename

使用上面的print('data')給出(手工包裝):

[{'ModuleName': 'myTestModule'}, 
 {'Version': 1.0}, 
 {'ModuleNumbers': [96, 97, 98, 99]}, 
  Message(name=Signal4, DLC=8, object=None, signals[...]), 
  Message(name=AO2_, DLC=8, object=RX2, signals[])]

print(data[3].signals[2]['ValueTable']['items'][2])給出:

Item(name=DONE, value=3)

當然,應酌情添加更多類。

暫無
暫無

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

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