安全性
密码、密钥、数据库地址等敏感信息不能写死在代码里,也不能暴露到仓库中。
一个应用不能只在本地跑通,还要能在开发、测试、生产等不同环境中安全稳定运行。环境配置和日志体系,就是应用程序的“安全自适应生存法则”:配置让程序适配环境,日志让问题可追踪。
同一套代码通常会运行在多个环境里,比如本地开发、测试服务器和生产服务器。不同环境的数据库地址、密钥、日志级别、调试模式都不一样。
安全性
密码、密钥、数据库地址等敏感信息不能写死在代码里,也不能暴露到仓库中。
环境自适应
一套代码根据环境变量切换配置,减少重复代码和维护成本。
运行可追溯
通过日志记录时间、环境、事件级别和请求上下文,方便快速排查问题。
核心问题可以概括为一句话:应用需要在“开发 / 生产”等不同环境中安全运行。
环境变量分层的作用,是把“代码逻辑”和“运行配置”分开。代码负责业务,配置负责告诉代码当前运行在哪里、连接哪个数据库、使用什么密钥。
识别环境身份
通过环境变量判断当前是开发环境、测试环境还是生产环境。
加载正确配置
根据不同环境加载不同数据库地址、日志级别、调试开关等配置项。
守护隐私安全
敏感信息只走 .env 文件或服务器环境变量,不写死在业务代码中。
常见环境配置可以这样拆:
| 配置项 | 开发环境 | 生产环境 |
|---|---|---|
APP_ENV |
dev |
prod |
DEBUG |
true |
false |
DATABASE_URL |
本地数据库地址 | 生产数据库地址 |
SECRET_KEY |
本地测试密钥 | 生产安全密钥 |
LOG_LEVEL |
DEBUG |
INFO / WARNING |
FastAPI 项目里可以用 Pydantic Settings 或类似方式读取环境变量。重点不是工具本身,而是让配置集中管理。
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings): app_env: str = "dev" debug: bool = True database_url: str secret_key: str log_level: str = "INFO"
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8")
settings = Settings()对应 .env 示例:
APP_ENV=devDEBUG=trueDATABASE_URL=mysql+pymysql://root:password@localhost:3306/fastapi_demoSECRET_KEY=change-meLOG_LEVEL=DEBUG配置读取后,业务代码只使用 settings.database_url 这类变量,不直接写死真实地址和密钥。
日志不是随便 print(),而是要留下能排查问题的关键线索。
日志四大记忆要素:
| 要素 | 说明 |
|---|---|
| 时间戳 | 记录精确时间,方便按时间线排查 |
| 环境身份 | 标明开发、测试或生产环境 |
| 事件级别 | 区分 DEBUG、INFO、WARNING、ERROR |
| 上下文 | 记录请求 ID、接口路径、用户 ID、异常信息等 |
Loguru 是一个 Python 日志工具,配置简单,适合快速搭建项目日志体系。
开发环境适合同时输出到控制台和文件,方便边调试边查看历史记录。
from loguru import logger
logger.add( "logs/dev.log", level="DEBUG", rotation="10 MB", retention="7 days", encoding="utf-8",)开发环境可以保留更多调试信息,但也要避免输出密码、密钥等敏感内容。
生产环境通常更强调文件输出、日志轮转和资源控制。
from loguru import logger
logger.add( "logs/prod_{time:YYYY-MM-DD}.log", level="INFO", rotation="00:00", retention="30 days", compression="zip", encoding="utf-8",)生产环境要减少噪音,只记录重要信息,并按天分割,避免日志文件无限增大。
Loguru 关键特性:
| 特性 | 作用 |
|---|---|
| 控制台输出 | 开发时直接查看运行状态 |
| 文件输出 | 保留历史问题线索 |
| 日志级别 | 控制不同环境输出哪些内容 |
| 日志轮转 | 按大小或时间拆分文件 |
| 保留策略 | 自动清理过旧日志,节省资源 |
如果前面已经做了统一错误处理,可以把日志体系和 request_id 结合起来,让一次请求的链路更完整。
import timeimport uuid
from fastapi import Requestfrom loguru import logger
async def request_log_middleware(request: Request, call_next): request_id = str(uuid.uuid4()) request.state.request_id = request_id
start = time.time() response = await call_next(request) cost_ms = round((time.time() - start) * 1000, 2)
logger.info( "request_id={} method={} path={} status={} cost_ms={}", request_id, request.method, request.url.path, response.status_code, cost_ms, )
response.headers["X-Request-ID"] = request_id return response这样前端、错误响应和日志里都能看到同一个 request_id。
拆分配置项:确认哪些配置会随环境变化,比如数据库地址、密钥、日志级别。
建立 .env.example:只保留字段说明和示例值,不放真实敏感信息。
集中读取配置:通过 Settings 类或配置模块统一读取环境变量。
配置日志输出:开发环境输出控制台和文件,生产环境以文件为主并开启轮转。
接入请求日志:在中间件里记录 request_id、路径、状态码和耗时。
补齐忽略规则:把 .env、真实日志文件、临时文件加入 .gitignore。
.envlogs/*.log__pycache__/.venv/忽略规则的核心,是避免把敏感配置、运行日志、虚拟环境和缓存文件提交到仓库。
# 实现环境变量分层管理和日志体系
1. 环境变量分层:支持开发 / 生产环境;2. 敏感信息只走环境变量 / 配置层,不写死在业务代码;3. 建立日志体系:日志文件用于留痕与排障,避免重复和噪音;4. 日志需要包含时间戳、环境身份、事件级别、请求 ID 和关键上下文;5. 使用 Loguru,开发环境输出控制台 + 文件,生产环境仅文件输出并按天分割;6. 补齐 .gitignore,避免提交 .env、logs、虚拟环境和缓存文件。