pydantic-settingsで環境変数を読み込む方法
今回はpydantic-settingsを用いて環境変数を読み込むと同時に、環境変数の値のバリデーションをしてみようと思います。
pydantic-settingsとは?
pydantic-settingsは環境変数やシークレットファイルを読み込んで利用するための機能をpydanticから拡張したものになっています。通常Pythonで環境変数を読み込むときはos
モジュールを利用することが多いかと思いますが、pydantic-settingsを利用するとpydanticに備わっているバリデーション機能などを利用することができるため、より安全に環境変数などを扱うことができます。
早速使ってみる
今回はpydantic-settingsから.env
の取り扱いおよび、pydanticからバリデーションの機能を紹介します。以下を参考にしていただければと思います。
環境構築
uv
を利用して環境を整えます。
uv init pydantic_settings_env -p 3.12
cd pydantic_settings_env
uv add pydantic-settings
また、今回は以下のような環境変数を定義しようと思います。
INT_VALUE=1
STRING_FROM_CHOICE=hoge
コードの実装
それではまずは以下のコードで環境変数を読み込みます。
from pydantic import Field, field_validator
from pydantic_settings import BaseSettings, SettingsConfigDict
class Envs(BaseSettings):
INT_VALUE: int = Field(description="Int value")
STRING_FROM_CHOICE: str = Field(description="String value")
model_config = SettingsConfigDict(env_file='.env')
@field_validator('STRING_FROM_CHOICE', mode='before')
@classmethod
def validate_string(cls, value: str) -> str:
if value not in ["hoge", "fuga"]:
raise ValueError("Invalid string was specified")
return value
@field_validator('INT_VALUE', mode='after')
@classmethod
def validate_int(cls, value: int) -> str:
if value not in range(1, 101):
raise ValueError("Invalid int was not in target range.")
return value
print(Envs())
まずは必要な機能をインポートします。pydantic.Field
はフィールドの定義をし、pydantic.field_validator
は読み込んだ環境変数のバリデーションに利用します。pydantic_settings.BaseSettings
とpydantic_settings.SettingsConfigDict
が今回利用する環境変数の取り扱いに重要な要素になります。
pydantic-settingsで環境変数を扱うには、まずpydantic_settings.BaseSettings
を継承したクラスを定義する必要があります。また、そのクラス内でmodel_config = SettingsConfigDict(env_file=".env")
を指定することで、このクラスで環境変数ファイルを読み込むことができるようになります。
class Envs(BaseSettings):
model_config = SettingsConfigDict(env_file=".env")
この準備が完了すれば、あとはpydanticを利用するときの要領でFieldを定義します。今回はINT_VALUEとSTRING_FROM_CHOICEという名前の環境変数を取得したいので、それぞれフィールドを設定しています。
class Envs(BaseSettings):
INT_VALUE: int = Field(description="Int value")
STRING_FROM_CHOICE: str = Field(description="String value")
model_config = SettingsConfigDict(env_file='.env')
これで環境変数を読み込むことはできますが、合わせてバリデーションもできるようにしてみます。今回はINT_VALUEは1~100の値で、STRING_FROM_CHOICEはhogeまたはfuga以外の値が指定されるとエラーになるようにしています。
class Envs(BaseSettings):
...
@field_validator('STRING_FROM_CHOICE', mode='before')
@classmethod
def validate_string(cls, value: str) -> str:
if value not in ["hoge", "fuga"]:
raise ValueError("Invalid string was specified")
return value
@field_validator('INT_VALUE', mode='after')
@classmethod
def validate_int(cls, value: int) -> str:
if value not in range(1, 101):
raise ValueError("Invalid int was not in target range.")
return value
それではこのコードを実行してみましょう。
uv run load_env.py
# 結果
INT_VALUE=1 STRING_FROM_CHOICE='hoge'
INT_VALUEは1~100に治っていますし、STRING_FROM_CHOICEもhogeで候補の中に入っているのでエラーは出ません。それでは次に環境変数を以下のようにして両方ともバリデーションに引っかかる内容にしてみます。
INT_VALUE=1000
STRING_FROM_CHOICE=hogehoge
この設定で実行してみると、以下のようになりました。
uv run load_env.py
# 結果
Traceback (most recent call last):
File "/Users/user/Documents/Blog/blog_materials/pydantic_settings_env/main.py", line 26, in <module>
print(Envs())
^^^^^^
File "/Users/user/Documents/Blog/blog_materials/pydantic_settings_env/.venv/lib/python3.12/site-packages/pydantic_settings/main.py", line 193, in __init__
super().__init__(
File "/Users/user/Documents/Blog/blog_materials/pydantic_settings_env/.venv/lib/python3.12/site-packages/pydantic/main.py", line 253, in __init__
validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pydantic_core._pydantic_core.ValidationError: 2 validation errors for Envs
INT_VALUE
Value error, Invalid int was not in target range. [type=value_error, input_value='1000', input_type=str]
For further information visit https://errors.pydantic.dev/2.11/v/value_error
STRING_FROM_CHOICE
Value error, Invalid string was specified [type=value_error, input_value='hogehoge', input_type=str]
For further information visit https://errors.pydantic.dev/2.11/v/value_error
以下のエラーのように、指定された値(input_value)に対してValueErrorが出ているのが確認できました。
INT_VALUE
Value error, Invalid int was not in target range. [type=value_error, input_value='1000', input_type=str]
For further information visit https://errors.pydantic.dev/2.11/v/value_error
STRING_FROM_CHOICE
Value error, Invalid string was specified [type=value_error, input_value='hogehoge', input_type=str]
For further information visit https://errors.pydantic.dev/2.11/v/value_error
このようにバリデーションを入れることにより、読み込んだ環境変数が想定した内容であるかをチェックすることができます。
まとめ
今回はpydantic-settingsを用いて環境変数を読み込み、バリデーションする機能を作ってみました。環境変数を扱う場合はos
モジュールの利用がよくみられますが、pydantic-settingsを利用することで信頼性の高いサービスの実装に寄与できると思うので、ぜひ使ったことがない方は使ってみてください。
Discussion