はじめに
1日1エントリでついに「765のななー」 nikkieです。
コードを見せずにタイトルだけで表現するのがなかなか難しかったのですが、pydantic-settingsの素振りの様子をお届けします。
目次
- はじめに
- 目次
- pydantic-settings
- BaseModel継承クラスの属性を、環境変数から設定できる
- BaseModel継承クラスの属性にデフォルト値を持たせ、環境変数から上書きできる
- 素振りのまとめ:ネストした設定の例
- 今回の学び(終わりにに代えて)
pydantic-settings
FastAPIなどでおなじみのパースライブラリ Pydantic1。
パースすることで実行時の型のバリデーションとして機能し、とても便利です。
そんなPydanticの機能を設定に適用できるのが、pydantic-settings!
Pydantic Settings provides optional Pydantic features for loading a settings or config class from environment variables or secrets files.
pip install pydantic-settings
して使い始められます。
pydantic_settingsのBaseSettings
について、少し込み入った例で素振りします。
BaseModel継承クラスの属性を、環境変数から設定できる
今回の素振りの題材は、「環境変数からConfigを設定できる」。
こんな感じです
% AWESOME_STRING=awesome AWESOME_NUMBER=765 uv run script.py awesome=AwesomeModel(string='awesome', number=765)
参照したのは https://docs.pydantic.dev/latest/concepts/pydantic_settings/#parsing-environment-variable-values
from pydantic import BaseModel from pydantic_settings import BaseSettings, SettingsConfigDict class AwesomeModel(BaseModel): string: str number: int class Config(BaseSettings): model_config = SettingsConfigDict(env_nested_delimiter="_") awesome: AwesomeModel config = Config() print(config)
pydantic_settings.BaseSettings
を継承したConfig
クラスに、AwesomeModel
(pydantic.BaseModel
を継承)を持たせていますAwesomeModel
はstring
とnumber
を持ちます- これらを環境変数から指定する際の書式を指定するのが
env_nested_delimiter="_"
- これらを環境変数から指定する際の書式を指定するのが
- 以下の環境変数で設定できます
AWESOME_STRING
->AwesomeModel
のstring
を指定AWESOME_NUMBER
->AwesomeModel
のnumber
を指定
BaseModel継承クラスの属性にデフォルト値を持たせ、環境変数から上書きできる
AwesomeModel
にはデフォルト値を設定できます。
デフォルト値を使えばよいとき、ユーザは環境変数での指定を省略できるわけです。
説明のためにFabulousModel
を追加しました。
class FabulousModel(BaseModel): string: str = "fabulous" number: int = 108 class Config(BaseSettings): model_config = SettingsConfigDict(env_nested_delimiter="_") fabulous: FabulousModel = FabulousModel() # デフォルト値の設定がポイント config = Config() print(config)
Configには、すべてデフォルト値を持ったBaseModel
(を継承したクラス)を持たせています。
このときのポイントは、FabulousModel
をインスタンス化して、デフォルト値に設定している点です2。
これをしていないと、値が指定されていないという解釈になり、Configが作れません。
https://docs.pydantic.dev/latest/errors/validation_errors/#missing
pydantic_core._pydantic_core.ValidationError: 1 validation error for Config fabulous Field required [type=missing, input_value={}, input_type=dict]
デフォルト値を使う例
% uv run script.py fabulous=FabulousModel(string='fabulous', number=108)
環境変数で上書きする例
% FABULOUS_STRING=foo FABULOUS_NUMBER=283 uv run script.py fabulous=FabulousModel(string='foo', number=283)
素振りのまとめ:ネストした設定の例
AwesomeModel
も使うとこんな感じです。
class Config(BaseSettings):
model_config = SettingsConfigDict(env_nested_delimiter="_")
+ awesome: AwesomeModel
fabulous: FabulousModel = FabulousModel()
% AWESOME_STRING=awesome AWESOME_NUMBER=765 uv run script.py awesome=AwesomeModel(string='awesome', number=765) fabulous=FabulousModel(string='fabulous', number=108)
AwesomeModel
にデフォルト値を一部設定してもこのままで動きます。
今回の学び(終わりにに代えて)
当初以下のように書いていて、missingのエラーが出ていました。
class Config(BaseSettings): model_config = SettingsConfigDict(env_nested_delimiter="_") awesome: AwesomeModel fabulous: FabulousModel
ステップ・バイ・ステップで手を動かしたところ、全てデフォルト値が指定されているBaseModel
(を継承したクラス)の場合は、BaseSettings
を継承したクラスでインスタンスをデフォルト値として持たせる必要があると分かりました。
素振りの例でさらにAwesomeModel
のnumber
にもデフォルト値を設定するならば、Config
ではawesome: AwesomeModel = AwesomeModel()
とインスタンスをデフォルト値にすることになります(全ての属性がデフォルト値を持つFabulousModel
と同様というわけです)
- 過去記事より ↩
-
このあたりが関係するんでしょうか?「Unlike pydantic
BaseModel
, default values ofBaseSettings
fields are validated by default.」 https://docs.pydantic.dev/latest/concepts/pydantic_settings/#validation-of-default-values↩