初期タスク
- .yamlファイルから重要な設定を読み取る必要があります。
- 構成構造は、データクラスを使用して記述されます。
- デシリアライズ中に型チェックを実行する必要があり、データが無効な場合は例外がスローされます。
つまり、簡単に言うと、次の形式の関数が必要です。
def strict_load_yaml(yaml: str, loaded_type: Type[Any]):
"""
Here is some magic
"""
pass
そして、この関数は次のように使用されます。
@dataclass
class MyConfig:
"""
Here is object tree
"""
pass
try:
config = strict_load_yamp(open("config.yaml", "w").read(), MyConfig)
except Exception:
logging.exception("Config is invalid")
構成クラス
ファイルconfig.py
は次のようになります。
from dataclasses import dataclass
from enum import Enum
from typing import Optional
class Color(Enum):
RED = "red"
GREEN = "green"
BLUE = "blue"
@dataclass
class BattleStationConfig:
@dataclass
class Processor:
core_count: int
manufacturer: str
processor: Processor
memory_gb: int
led_color: Optional[Color] = None
動作しないオプション
, ? . yaml- ?
PyYaml load
:
from pprint import pprint
from yaml import load, SafeLoader
yaml = """
processor:
core_count: 8
manufacturer: Intel
memory_gb: 8
led_color: red
"""
loaded = load(yaml, Loader=SafeLoader)
pprint(loaded)
:
{'led_color': 'red', 'memory_gb': 8, 'processor': {'core_count': 8, 'manufacturer': 'Intel'}}
Yaml , . , **args
:
parsed_config = BattleStationConfig(**loaded) pprint(parsed_config)
:
BattleStationConfig(processor={'core_count': 8, 'manufacturer': 'Intel'}, memory_gb=8, led_color='red')
! ! … -. processor ? .
Python Processor
. stackowerflow.
, yaml-
stackowerflow PyYaml , yaml- . YAMLObject
, config_with_tag.py
:
from dataclasses import dataclass
from enum import Enum
from typing import Optional
from yaml import YAMLObject, SafeLoader
class Color(Enum):
RED = "red"
GREEN = "green"
BLUE = "blue"
@dataclass
class BattleStationConfig(YAMLObject):
yaml_tag = "!BattleStationConfig"
yaml_loader = SafeLoader
@dataclass
class Processor(YAMLObject):
yaml_tag = "!Processor"
yaml_loader = SafeLoader
core_count: int
manufacturer: str
processor: Processor
memory_gb: int
led_color: Optional[Color] = None
:
from pprint import pprint
from yaml import load, SafeLoader
from config_with_tag import BattleStationConfig
yaml = """
--- !BattleStationConfig
processor: !Processor
core_count: 8
manufacturer: Intel
memory_gb: 8
led_color: red
"""
a = BattleStationConfig
loaded = load(yaml, Loader=SafeLoader)
pprint(loaded)
?
BattleStationConfig(processor=BattleStationConfig.Processor(core_count=8, manufacturer='Intel'), memory_gb=8, led_color='red')
. yaml- . , Color
- . YAMLObject
? ? , .
class Color(Enum, YAMLObject):
RED = "red"
GREEN = "green"
BLUE = "blue"
:
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
. yaml-, .
marshmallow
stackowerflow marshmallow , JSON-. , , , yaml JSON. class_schema
, -:
from pprint import pprint
from yaml import load, SafeLoader
from marshmallow_dataclass import class_schema
from config import BattleStationConfig
yaml = """
processor:
core_count: 8
manufacturer: Intel
memory_gb: 8
led_color: red
"""
loaded = load(yaml, Loader=SafeLoader)
pprint(loaded)
BattleStationConfigSchema = class_schema(BattleStationConfig)
result = BattleStationConfigSchema().load(loaded)
pprint(result)
, , :
marshmallow.exceptions.ValidationError: {'led_color': ['Invalid enum member red']}
, marshmallow enum, . yaml- :
processor: core_count: 8 manufacturer: Intel memory_gb: 8 led_color: RED
, , :
BattleStationConfig(processor=BattleStationConfig.Processor(core_count=8, manufacturer='Intel'), memory_gb=8, led_color=<Color.RED: 'red'>)
, yaml-. marshmallow :
Settingby_value=True
. This will cause both dumping and loading to use the value of the enum.
, metadata
field
:
@dataclass
class BattleStationConfig:
led_color: Optional[Color] = field(default=None, metadata={"by_value": True})
, "" , yaml-.
, :
def strict_load_yaml(yaml: str, loaded_type: Type[Any]):
schema = class_schema(loaded_type)
return schema().load(load(yaml, Loader=SafeLoader))
-, yaml.
ForwardRef
- ForwardRef ( ) marshmallow .
,
from dataclasses import dataclass, field
from enum import Enum
from typing import Optional, ForwardRef
@dataclass
class BattleStationConfig:
processor: ForwardRef("Processor")
memory_gb: int
led_color: Optional["Color"] = field(default=None, metadata={"by_value": True})
@dataclass
class Processor:
core_count: int
manufacturer: str
class Color(Enum):
RED = "red"
GREEN = "green"
BLUE = "blue"
marshmallow.exceptions.RegistryError: Class with name 'Processor' was not found. You may need to import the class.
また、クラスを上に移動するとProcessor
、マシュマロはColor
同様のエラーでクラスを失います。したがって、可能であれば、マシュマロでクラスを解析する場合は、クラスでForwardRefを使用しないでください。
コード
すべてのコードはGitHubリポジトリで入手できます。