Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

Pydantic BaseSettingsにおけるCLI引数、環境変数、コンストラクタ引数の優先順位

Posted at

概要

pydantic-settingsのBaseSettingsクラスの初期化における入力変数の優先順位を調べました。

結論としては、CLI引数 > コンストラクタ引数 > 環境変数 > 環境変数ファイル(dotenv) > デフォルト値の優先度でした。

検証コード

import os
import shutil
import sys
from pathlib import Path

from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict

TMPENV = "tmp/.env"


def setup_tmp_env():
    """一時的な.envファイルを設定する"""
    env_file = Path(TMPENV)
    tmp_dir = env_file.parent
    tmp_dir.mkdir(exist_ok=True)
    env_file.write_text("NAME=dotenv")
    return env_file


def cleanup_tmp_env():
    """一時的な.envファイルを削除する"""
    env_file = Path(TMPENV)
    tmp_dir = env_file.parent
    if tmp_dir.exists():
        shutil.rmtree(tmp_dir)


class SettingsA(BaseSettings):
    name: str = Field(default="", description="名前")

    model_config = SettingsConfigDict(
        env_file=TMPENV,  # デフォルトの.envファイルを指定
        case_sensitive=False,
        cli_parse_args=True,
        cli_ignore_unknown_args=True,
        extra="ignore",
    )


def setup_test():
    sys.argv = ["script.py"]
    if os.environ.get("NAME"):
        del os.environ["NAME"]
    cleanup_tmp_env()


def test_settings_with_cli_args():
    # デフォルト値
    setup_test()
    settings = SettingsA()
    assert settings.name == ""

    # CLI引数を設定
    setup_test()
    sys.argv = ["script.py", "--name", "cli"]
    settings = SettingsA()
    assert settings.name == "cli"

    # 環境変数を設定
    setup_test()
    os.environ["NAME"] = "env"
    settings = SettingsA()
    assert settings.name == "env"

    # dotenvを設定
    setup_test()
    setup_tmp_env()
    settings = SettingsA()
    assert settings.name == "dotenv"

    # コンストラクタ引数
    setup_test()
    settings = SettingsA(name="constructor")
    assert settings.name == "constructor"

    # CLI引数とコンストラクタ引数を設定(CLI引数が優先)
    setup_test()
    sys.argv = ["script.py", "--name", "cli"]
    settings = SettingsA(name="constructor")
    assert settings.name == "cli"

    # コンストラクタ引数と環境変数(コンストラクタ引数が優先)
    setup_test()
    os.environ["NAME"] = "env"
    settings = SettingsA(name="constructor")
    assert settings.name == "constructor"

    # 環境変数とdotenvを設定(環境変数が優先)
    setup_test()
    os.environ["NAME"] = "env"
    setup_tmp_env()
    settings = SettingsA()
    assert settings.name == "env"


if __name__ == "__main__":
    test_settings_with_cli_args()

おわりに

上記はデフォルトの優先順位の場合です。
優先順位は変更可能です。

基本的にはデフォルトの優先順位で良いと思いますが、CLI引数よりコンストラクタ引数を優先したり、環境変数より環境変数ファイルを優先したくなる可能性もあるかなと思いました。

0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?