在前 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,看看如何讓專案的日誌不只是文字,而是能被監控與分析的資料流。