[英]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 文件中使用標簽,並放棄使用名稱為Item1
、 Item2
的鍵(替換為標記對象列表)。
很難看到數據的確切結構,但第一步可能是制作 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
Name
和name
。
使用上面的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.