在前 11 天,我們已經把專案的「基礎建設」建起來了:環境、設定檔、專案結構、依賴管理、一鍵化工作流、程式風格、型別與資料契約,再到測試藍圖。
專案已經能穩定執行,並且確保品質。
但還缺一塊關鍵拼圖:設定與祕密管理(Configuration & Secrets Management)。
這是許多專案會踩的坑:
.env。今天,我們要建立一個「設定與祕密」的管理藍圖,從最簡單的 .env,到 pydantic-settings,再到雲端祕密服務,逐步提升安全性與工程化程度。
許多人一開始會用 .env 搭配 python-dotenv:
# .env
APP_ENV=dev
APP_DEBUG=true
DATABASE_URL=postgresql://user:pass@localhost/db
在程式裡讀取:
from dotenv import load_dotenv
import os
load_dotenv()
print(os.getenv("APP_ENV"))       # dev
print(os.getenv("DATABASE_URL"))  # postgresql://user:pass@localhost/db
👉 優點:簡單、直觀、快速上手。
👉 缺點:缺乏型別與驗證,.env 常被誤 commit,祕密容易外洩。
適合用在個人實驗或小型專案,但在團隊專案就需要更嚴謹的工具。
延續 Day 10 的 Pydantic v2,我們可以用 pydantic-settings 把環境變數「轉換成型別安全的設定物件」。
from pydantic_settings import BaseSettings, SettingsConfigDict
class AppSettings(BaseSettings):
    model_config = SettingsConfigDict(env_prefix="APP_")
    env: str = "dev"
    debug: bool = False
    database_url: str
settings = AppSettings()
print(settings.env, settings.debug, settings.database_url)
如果 .env 或環境變數有問題,會直接丟出 ValidationError,這比 os.getenv() 安全得多。
更進一步,我們還可以區分環境設定檔:
# .env.dev
APP_ENV=dev
APP_DEBUG=true
APP_DATABASE_URL=sqlite:///local.db
# .env.prod
APP_ENV=prod
APP_DEBUG=false
APP_DATABASE_URL=postgresql://user:pass@prod/db
在程式裡依 CI/CD 或環境參數載入對應設定,避免「開發正常、上線爆炸」。
👉 工程實務的好處:
APP_PORT=abc 認成 int)。當專案進入團隊或上雲環境,就不該再把祕密留在 .env 了。
常見做法是使用 雲端祕密管理服務:
以 AWS 為例,我們可以在部署環境透過 SDK 讀取:
import boto3
import json
client = boto3.client("secretsmanager")
resp = client.get_secret_value(SecretId="my-app/db")
db_config = json.loads(resp["SecretString"])
再把 db_config 餵給 pydantic-settings 的模型,保持型別安全。
👉 好處:
.env。👉 缺點:
最佳實務:本地用 .env 模擬,雲端用 Secret Manager 正式管理。
延續 Day 4 的「src/ + tests/」設計,我們可以這樣放置設定與祕密相關檔案:
my_project/
├─ src/my_project/
│   ├─ __init__.py
│   ├─ settings.py        # pydantic-settings 模型
│   ├─ secrets.py         # 雲端 Secrets Manager 讀取工具
│   └─ adapters/
│       └─ web.py
├─ .env.example           # 範例環境變數(不含祕密值)
├─ .gitignore             # 記得忽略 .env、.env.*
└─ tests/
    └─ test_settings.py   # 測試設定與驗證
這樣可以清楚地分層:
settings.py:設定模型與驗證。secrets.py:與雲端祕密服務的串接邏輯。.env.example:作為文件,提醒新進開發者需要哪些環境變數。把這三層組合起來,我們得到一個設定管理藍圖:
.env + pydantic-settings,快速迭代。pydantic-settings 載入。範例 CI 工作流(GitHub Actions):
name: ci
on: [push]
jobs:
  test:
    runs-on: ubuntu-latest
    env:
      APP_ENV: test
      APP_DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }}
    steps:
      - uses: actions/checkout@v4
      - run: pip install -r requirements.txt
      - run: pytest -q
這樣就能確保:
.env 永遠不要 commit,僅提供 .env.example。pydantic-settings 驗證,避免錯誤流入 runtime。.env。detect-secrets 或 Gitleaks)。設定與祕密管理,是工程化專案的安全防線。
.env:入門與本地測試。pydantic-settings:型別安全、驗證與分環境管理。透過這三層逐步演進,我們可以避免「API Key 洩漏」「環境錯亂」的風險,讓專案在安全性與維護性上更上一層樓 🚀。
明天 Day 13,我們將探討 結構化日誌:logging / structlog 與 JSON Log,看看如何讓專案的日誌不只是文字,而是能被監控與分析的資料流。