[英]Pydantic - parse a list of objects from YAML configuration file
我想從 YAML 文件中讀取對象列表:
- entry1:
attribute: "Test1"
amount: 1
price: 123.45
- entry2:
attribute: "Test1"
amount: 10
price: 56.78
對於這個數據結構,我創建了三個嵌套模型,如下所示:
# Models
class EntryValues(BaseModel):
attribute: str
amount: int
price: float
class Entry(BaseModel):
entry1: EntryValues
entry2: EntryValues
class Config(BaseModel):
__root__: list[Entry]
我讀取 YAML 配置文件的代碼如下所示:
# get YAML config path
def get_cfg_path() -> Path:
return CWD
# read YAML file
def read_cfg(file_name: str, file_path: Path = None) -> YAML:
if not file_path:
file_path = get_cfg_path()
if file_path:
try:
file = open(file_path / file_name, "r")
except Exception as e:
print(f"open file {file_name} failed", e)
sys.exit(1)
else:
return load(file.read())
else:
raise Exception(f"Config file {file_name} not found!")
現在我想將 YAML 的值解壓縮到我的模型中。 為此,我嘗試使用**
運算符解壓縮值。 我想我在這里又錯過了一個循環,但我無法讓它工作。
# Unpack and create config file
def create_cfg(file_name: str = None) -> Config:
config_file = read_cfg(file_name=file_name)
_config = Config(**config_file.data)
return _config
我將不勝感激任何幫助。
所以我在不使用 YAML 文件的情況下使用了我的模型結構。 我不太明白為什么以下會引發ValidationError
:
考慮以下條目列表(這與我從 YAML 文件中收到的數據結構相同):
entries = [
{'entry1': {'attribute': 'Test1', 'amount': 1, 'price': 123.45}},
{'entry2': {'attribute': 'Test2', 'amount': 10, 'price': 56.78}}
]
如果我運行以下簡單循環,那么 Pydantic 會拋出ValidationError
:
for entry in entries:
Entry(**entry)
錯誤:
ValidationError: 1 validation error for Entry
entry2
field required (type=value_error.missing)
但是,如果列表只包含一個條目字典,那么它可以工作:
class Entry(BaseModel):
entry1: EntryValues
#entry2: EntryValues
entries = [
{'entry1': {'attribute': 'Test1', 'amount': 1, 'price': 123.45}}
]
for entry in entries:
Entry(**entry)
有人可以解釋這個或我在這里做錯了什么嗎?
在您的更新中,第二種情況有效但第一種無效的原因是解包運算符( **
)采用一個包含所有必要鍵的字典對象。 在您的第一種情況下,您有一本包含所有必要信息的字典; 在第二個中,它分布在兩個字典中,它們不能一起解包。 一種可能的解決方法是將它們合並到一個字典中。 但據我了解,更好的解決方案是首先更改您的 YAML 以提供此功能,方法是刪除每行中的前兩個字符:
entry1:
attribute: "Test1"
amount: 1
price: 123.45
entry2:
attribute: "Test1"
amount: 10
price: 56.78
接着:
_config = Config(__root__=[Entry(**entries)])
您的代碼存在許多問題,但我認為您要做的是將 YAML 解析為字典並從每個項目中實例化一個EntryValues
。 看起來像這樣:
from pydantic import BaseModel
from pathlib import Path
from typing import List
import yaml
def create_cfg(file_name: str = None) -> Config:
config_file = read_cfg(file_name=file_name)
entries = yaml.safe_load(config_file)
_config = [
EntryValues(**di[name]) for di, name in zip(entries, ["entry1", "entry2"])
]
return _config
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.