Python3.7から追加されたdataclasses.dataclass
は、設定オブジェクトを定義する際に非常に便利です。このデコレータをつけるだけでコンストラクタを省略でき、各項目に型を指定すればpyright
やmypy
で型推論をして事前にバグを発見できます。
また、設定ファイルはPythonファイルだけではなく、テキストファイルとして保持できると便利なことがあります。そのため、YAML形式で保存/ロード可能な設定クラスを作成することを考えます。
以下に、YAML形式で保存/ロード可能な設定クラスの作成例を示します。
import pathlib
import dataclasses
import yaml
import inspect
@dataclasses.dataclass
class YamlConfig:
def save(self, config_path: pathlib.Path):
""" Export config as YAML file """
assert config_path.parent.exists(), f'directory {config_path.parent} does not exist'
def convert_dict(data):
for key, val in data.items():
if isinstance(val, pathlib.Path):
data[key] = str(val)
if isinstance(val, dict):
data[key] = convert_dict(val)
return data
with open(config_path, 'w') as f:
yaml.dump(convert_dict(dataclasses.asdict(self)), f)
@classmethod
def load(cls, config_path: pathlib.Path):
""" Load config from YAML file """
assert config_path.exists(), f'YAML config {config_path} does not exist'
def convert_from_dict(parent_cls, data):
for key, val in data.items():
child_class = parent_cls.__dataclass_fields__[key].type
if child_class == pathlib.Path:
data[key] = pathlib.Path(val)
if inspect.isclass(child_class) and issubclass(child_class, YamlConfig):
data[key] = child_class(**convert_from_dict(child_class, val))
return data
with open(config_path) as f:
config_data = yaml.full_load(f)
# recursively convert config item to YamlConfig
config_data = convert_from_dict(cls, config_data)
return cls(**config_data)
このクラスを使用すると、設定オブジェクトをYAMLファイルとして保存し、ロードすることができます。これにより、設定の管理が容易になります。
以上、PythonとYAMLとDataclassを活用した設定ファイルの管理について説明しました。この組み合わせを活用することで、設定の管理が一段と容易になります。.