正确做法是只在本地放.env文件并加入.gitignore,用python-dotenv加载;生产环境应使用平台原生secrets机制而非.env文件。

用 python-dotenv 加载环境变量最稳妥
硬编码密码或把 .env 文件提交到 Git 是常见翻车点。正确做法是:只在本地放 .env,把它加进 .gitignore,再用 python-dotenv 读取。它会自动忽略注释、跳过空行,并按 key=value 解析——注意等号前后不能有空格,否则值会带空格,导致连接失败。
安装后,在项目根目录创建 .env:
DB_HOST=localhost DB_USER=appuser DB_PASSWORD=super-secure-pass-123 DB_NAME=myapp
代码里这样用:
from dotenv import load_dotenv
import os
<p>load_dotenv() # 自动加载项目根目录下的 .env</p><p><span>立即学习</span>“<a href="https://pan.quark.cn/s/00968c3c2c15" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">Python免费学习笔记(深入)</a>”;</p><p>db_url = f"postgresql://{os.getenv('DB_USER')}:{os.getenv('DB_PASSWORD')}@{os.getenv('DB_HOST')}/{os.getenv('DB_NAME')}"-
load_dotenv()默认只加载一次,多次调用无副作用 - 如果
.env不在根目录,必须显式传路径:load_dotenv('.config/.env') -
os.getenv('KEY', 'default')可设默认值,但敏感项不建议设默认密码
生产环境别依赖 .env 文件
服务器上不应存 .env 文件——权限难控、易被日志打印、容器镜像可能意外打包进去。Kubernetes、Docker Swarm 或云平台(如 AWS ECS、Heroku)都提供原生的 secrets 管理机制。
SkillSub Pro - Python 题解与代码注释双功能技能功能概述SkillSub Pro - Python 题解与代码注释双功能技能是一项面向实际任务的技能,主要用于SkillSub Pro 是一个 Python 题解生成与代码注释的 双功能合体技能 ,专为学生、算法学习者和开发者设计;✅ 一个技能,两种用途 :;核心要点📝 题解模式 :输入题目/题号,自动生成完整 Python 题解(含详细注释、解题思路、复杂度分析);💬 注释模式 :输入 Python 代码,自动添加详细中。它将相关步骤、
例如 Docker Compose 中用 secrets:
services:
web:
image: myapp:latest
secrets:
- db_password
secrets:
db_password:
file: ./secrets/db_password.txt然后在容器内通过 /run/secrets/db_password 读取(内容是纯文本,无换行),代码里要打开并 strip:
with open('/run/secrets/db_password', 'r') as f:
password = f.read().strip()- 不要把 secret mount 到常规路径(如
/app/.env),避免误提交或日志泄露 - Cloud Run / Lambda 等无状态服务,应从平台 secret manager(如
os.environ.get('DB_PASSWORD'))直接读取,而非文件 - 本地开发和 CI 流水线要用不同机制:CI 用 encrypted variables(GitHub Secrets / GitLab CI Variables)
SQLAlchemy 连接字符串里别拼接密码
直接用 f"..." 拼接密码,一旦日志级别设为 DEBUG,整个连接串(含密码)就会明文打出来。更安全的方式是让 SQLAlchemy 自动解析 URL,且禁用 echo 日志输出密码:
from sqlalchemy import create_engine
<p>engine = create_engine(
os.getenv("DATABASE_URL"), # 如 postgresql://user:@host/db
echo=False, # 关键:关闭 SQL 日志
echo_pool=False,
pool_pre_ping=True,
)-
DATABASE_URL应提前组装好(比如 CI 中拼接),避免运行时拼接 - 若必须动态构造,用
urllib.parse.urlunparse,而不是字符串格式化 - PostgreSQL 的
psycopg2支持从.pgpass读密码,但 Python 生态中极少用,维护成本高
检查是否意外泄露了密码
最容易被忽略的是:日志、异常堆栈、调试响应、IDE 快照、Git 历史。哪怕删了 .env,旧 commit 里可能还藏着密码。
- 用
git log -p -S "DB_PASSWORD"扫描历史,确认没提交过敏感值 - 在
logging.basicConfig()中禁用%(message)s外的敏感字段输出 - Django 用户注意:
DEBUG=True时模板错误页会显示完整上下文,包括环境变量——生产务必关掉 - Pydantic v2+ 的
BaseSettings已弃用,改用pydantic-settings,它支持case_sensitive=False和自动类型转换,但不会自动过滤密码字段,仍需手动处理
真正麻烦的不是“怎么藏”,而是“怎么确保没漏”。每次部署前花 30 秒 grep 一遍 DB_ 和 PASSWORD,比事后修漏洞省十倍力气。

















