🎉

pydantic-settingsで実行環境から環境変数を読み込む方法

に公開

今回は昨日に続いて、pydantic-settingsを利用して環境変数を取り扱おうと思います。昨日は.envファイルを読み込むように設定しましたが、今回はPython実行環境にすでに設定されている環境変数を読み込む方法を共有します。

https://zenn.dev/akasan/articles/0a4136eb60030d

早速やってみる!

先ほど書いたように、今回は.envから読み込むのではなく、実行環境にすでに登録されている環境変数を読み込もうと思います。

環境構築

今回はuvで環境構築するとともに、シェルに環境変数を登録します。

uv init pydantic_settings_env -p 3.12
cd pydantic_settings_env
uv add pydantic-settings

export INT_VALUE=1
export STRING_FROM_CHOICE=hoge

コードの実装

.envファイルから読み込む場合はmodel_configを利用する必要があるのですが、すでに環境変数になっているものを読み込むのはよりシンプルに記載できます。バリデーションは昨日と同じものを実装していますが、読み込みたい環境変数をpydanticを利用する時の要領で指定するだけで読み込むことができます。

load_env.py
from pydantic import Field, field_validator
from pydantic_settings import BaseSettings

class Envs(BaseSettings):
    INT_VALUE: int = Field(description="Int value")
    STRING_FROM_CHOICE: str = Field(description="String value")

    @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())

早速これを実行してみましょう。

uv run load_env.py

# 結果
INT_VALUE=1 STRING_FROM_CHOICE='hoge'

想定していた結果が得られました。

それではバリデーションに引っかかるように環境変数を変更してみます。

export INT_VALUE=1000
export STRING_FROM_CHOICE=hogehoge

この状態でコードを実行してみます。昨日の結果と同様、INT_VALUEとSTRING_FROM_CHOICE両方のバリデーションが実行されデータに問題があることを検知してくれました。

uv run load_env.py

# 結果
Traceback (most recent call last):
  File "/Users/user/Documents/Blog/blog_materials/pydantic/pydantic-settings/pydantic_settings_env_from_shell/main.py", line 24, in <module>
    print(Envs())
          ^^^^^^
  File "/Users/user/Documents/Blog/blog_materials/pydantic/pydantic-settings/pydantic_settings_env_from_shell/.venv/lib/python3.12/site-packages/pydantic_settings/main.py", line 193, in __init__
    super().__init__(
  File "/Users/user/Documents/Blog/blog_materials/pydantic/pydantic-settings/pydantic_settings_env_from_shell/.venv/lib/python3.12/site-packages/pydantic/main.py", line 250, 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.12/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.12/v/value_error

まとめ

今回はpydantic-settingsを利用して、すでに環境に登録されている環境変数を読み込む方法を紹介しました。実装自体は.envから読み込むものと比較して少し少ない記述で収めることができます。主な用途としては、例えばGoogle CloudのCloud Runで環境変数を設定してサーバを起動している状態でアプリケーションサーバを実装する際の読み込み手法として利用することがあるかと思います。環境変数をPythonで取り扱う方はぜひ利用してみてください。

Discussion