0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

#0155(2025/05/30)Pydantic BaseSettings

Last updated at Posted at 2025-05-30

Pydantic BaseSettings 攻略ガイド

Why BaseSettings?

  • 環境依存値を型安全に管理し、設定ミスをゼロに。
  • ローカル → CI → ステージング → 本番 まで同一コードを使い回し。
  • Secrets・Kubernetes・リモート設定サービス との統合を最小コードで実現。

1. インストール & バージョンガイド

  • 現行最新版 (v2.6 〜)

    pip install "pydantic[dotenv]~=2.6"
    
    • dotenv extras を入れると .env 自動読込が可能。
    • 依存: Python 3.8+
  • レガシー (v1.x)

    pip install "pydantic<2"
    
    • 新規プロジェクトなら v2 を強く推奨。

バージョン判定ワンライナー

import pydantic, sys
print(pydantic.version.VERSION, sys.version)

v1 → v2 で得られる主なメリット

  • 40〜50% 高速化(新パースエンジン)
  • バリデータがデコレータ一発 @field_validator
  • 型エラー時のメッセージがより詳細 & 多言語化
  • settings_customise_sources によるカスタムソース統合が簡潔

2. 基本の使い方 ― 5 分で “Hello, Settings”

# settings.py
from pydantic import BaseSettings
class Settings(BaseSettings):
    app_name: str = "MyApp"
    port: int
    debug: bool = False

    model_config = {
        "env_prefix": "APP_",       # 全フィールド共通プレフィックス
        "env_file": ".env",         # カレントの .env を読込
        "env_file_encoding": "utf-8",
    }

settings = Settings()   # ⚡️ 一行で解決

.env サンプル

APP_PORT=8000
APP_DEBUG=true

ここだけは覚えて:読み込み優先順位

  1. 直接 Settings(port=9999) など コード引数
  2. 環境変数(例: export APP_PORT=8888
  3. .env ファイル
  4. デフォルト値(クラス宣言内)

インフラ→CI→ローカル の上書き戦略がシンプル!


3. よく使うテクニック集

3‑1. シングルトン化で多重ロード防止

from functools import lru_cache
@lru_cache
def get_settings():
    return Settings()

→ FastAPI では Depends(get_settings) で DI。

3‑2. プレフィックス & エイリアス

from pydantic import Field
class API(BaseSettings):
    url: str = Field(alias="SERVICE_URL")
    timeout: int = Field(default=5, alias="SERVICE_TIMEOUT")

外部サービス名変更時に Python コードは無改修

3‑3. Secret 値 & マスキング

from pydantic import SecretStr
class Creds(BaseSettings):
    password: SecretStr
  • print(creds)password=SecretStr('**********')
  • creds.password.get_secret_value() で生値取得。

3‑4. 型変換 Tips

  • bool"true" "True" "1" など case-insensitiveTrue
  • list[int]"1,2,3" または JSON 文字列 [1, 2, 3] を受容。
  • Path 型は OS パスセパレータを自動調整(Windows↔Unix)。

4. 応用:マルチ環境 & カスタムソース

4‑1. 環境別 .env を自動切替

import os
class EnvSettings(BaseSettings):
    env: str = os.getenv("ENV", "local")
    model_config = {"env_file": f".env.{env}"}
  • ENV=prod python main.py.env.prod を読込。
  • CI では .env.ci を用意するとセキュア。

4‑2. YAML + HTTP + env の 3 層構成例

from pathlib import Path
import yaml, requests
from pydantic import BaseSettings

def yaml_source(_: BaseSettings):
    yml = Path("config.yaml")
    return yaml.safe_load(yml.read_text()) if yml.exists() else {}

def http_source(_: BaseSettings):
    r = requests.get("http://config-svc.local/config")
    return r.json() if r.ok else {}

class Cfg(BaseSettings):
    feature_flag: bool = False
    user_quota: int = 100

    model_config = {
        "settings_customise_sources": lambda cls, _: (
            http_source, yaml_source, *BaseSettings.settings_customise_sources()
        )
    }
  • HTTP > YAML > env > .env > default の優先度が実現。

4‑3. 完全ネストモデル

class PG(BaseSettings):
    host: str
    port: int = 5432
    db: str
class Redis(BaseSettings):
    url: str
class Global(BaseSettings):
    pg: PG
    redis: Redis
  • 必要な環境変数は PG_HOST, PG_PORT, REDIS_URL 等。
  • .env が肥大化したらファイル分割 or Prefix で整理。

5. 運用:テスト・リロード・フレームワーク統合

5‑1. テストでの環境変数上書き

import pytest
from settings import Settings

def test_debug(monkeypatch):
    monkeypatch.setenv("APP_DEBUG", "true")
    assert Settings().debug is True
  • monkeypatch はテスト終了後に自動リセット。

5‑2. 設定ホットリロード(watchdog 使用例)

from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer

class ReloadHandler(FileSystemEventHandler):
    def on_modified(self, event):
        if event.src_path.endswith(".env"):
            Settings.model_reset()  # v2 のみ
            print("🔄 Settings reloaded")

5‑3. フレームワーク接続例

  • FastAPI: settings = Settings(); app = FastAPI() → 依存注入でシングルトン共有。
  • Celery: Worker 起動スクリプト内で os.environ.update(Settings().model_dump())
  • Django: settings.py 内で from .settings_obj import Settings。DjangoConf を置換可能。

6. 移行 & バージョン差分チェックリスト

  • Config → model_config に置換。
  • @validator@field_validator へリネーム。
  • json() / dict() → model_dump_json() / model_dump()
  • **allow_mutation=False → model_config = {"frozen": True}`。
  • parse_obj_as → pydantic.TypeAdapter().validate_python(...)
  • settings_customise_sources は新 API 名。旧 customise_sources は削除。

🚩 まずはテストを用意 → pip install "pydantic[dotenv]>=2" --upgrade → エラーを上から潰す。


7. よくある落とし穴と対策

  • インスタンスを複数生成 → 毎回ファイル I/O → 遅延。
    @lru_cache を付けて シングルトン 化。
  • bool 変換の罠"false" "0" "no" 以外のスペルは全部 True 扱い。
    .env では 小文字 true/false を統一。
  • 巨大ネスト → 環境変数名が長大化。
    .env を複数ファイルに分割 or YAML/HTTP を併用。
  • Secret の誤露出print(settings) がパスワードを表示。
    SecretStr を必ず使う & 発行先ログを確認。
  • 文字エンコーディング → Windows の CP932 で .env が文字化け。
    model_config["env_file_encoding"] = "utf-8" を明示。

8. スニペット集 & リンク

8‑1. AWS 認証キーの最小定義

class AWS(BaseSettings):
    access_key: str
    secret_key: SecretStr
    region: str = "ap-northeast-1"
    model_config = {"env_prefix": "AWS_"}

8‑2. 実行時 CPU コア数でデフォルト設定

import os, multiprocessing
class Perf(BaseSettings):
    workers: int = multiprocessing.cpu_count() * 2 + 1

8‑3. Slack Webhook + Proxy 設定

class Slack(BaseSettings):
    webhook_url: str = Field(..., alias="SLACK_WEBHOOK")
    proxy: str | None = Field(None, alias="HTTPS_PROXY")

8‑4. 公式 & 実例ドキュメント


🏁 まとめ

“設定はコードの一部” — BaseSettings で “人間が触る領域” を統制し、アプリ本体は “型保証された設定オブジェクト” に依存するだけ。これが 運用・開発・セキュリティ をラクにする最短ルート!

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?