你想知道如何用python-dotenv适配开发、测试、生产等不同环境的配置管理,核心思路是为每个环境单独创建专属的.env配置文件(比如.env.dev、.env.test、.env.prod),再通过指定加载文件或环境变量标记环境的方式,让代码自动加载对应环境的配置,既保证各环境配置隔离,又不用修改核心代码。
下面讲两种最常用的方案,方案一(指定文件加载)简单直观,适合本地开发/小型项目;方案二(环境变量自动切换)更规范,适合团队协作/线上部署,是行业最佳实践,建议重点掌握。
前置准备
确保已安装
python-dotenv(任意稳定版均可,包括你之前的 1.2.1):pipinstallpython-dotenv>=1.0.0在项目根目录为每个环境创建独立的配置文件,遵循统一命名规范(推荐
.env.环境名),示例文件结构:你的项目/ ├── .env.dev # 开发环境(本地调试,数据库用本地、调试模式开启) ├── .env.test # 测试环境(测试服务器,数据库用测试库、日志级别INFO) ├── .env.prod # 生产环境(线上服务器,数据库用线上、调试模式关闭,密钥用正式的) ├── .gitignore # 关键:忽略所有.env配置文件,防止敏感信息提交 └── main.py # 项目入口文件(加载配置的核心逻辑写在这里)各配置文件按
KEY=VALUE写专属配置,相同配置键名保持一致,值随环境变化,示例:.env.dev(开发环境):# 开发环境-本地数据库 DB_URL=mysql+pymysql://root:123456@localhost:3306/dev_db # 开启调试模式 DEBUG=True # 日志级别-详细 LOG_LEVEL=DEBUG # 本地接口地址 API_BASE_URL=http://127.0.0.1:8000.env.prod(生产环境):# 生产环境-线上数据库 DB_URL=mysql+pymysql://prod_user:ProdPass123@prod-db:3306/prod_db # 关闭调试模式(必关!防止泄露信息) DEBUG=False # 日志级别-精简 LOG_LEVEL=WARNING # 线上接口地址 API_BASE_URL=https://api.xxx.com.env.test(测试环境):配置介于开发和生产之间,用测试库即可。
完善
.gitignore,忽略所有真实配置文件,只保留示例文件(可选):# 忽略所有环境的配置文件 .env .env.* # 可选:保留配置示例,给团队成员参考格式(无真实值) !.env.example可创建
.env.example作为模板,只写键不写值:# 配置示例:复制为 .env.xxx 并填写对应环境的真实值 DB_URL= DEBUG= LOG_LEVEL= API_BASE_URL=
方案一:手动指定文件加载(简单直观,适合本地开发)
核心是通过load_dotenv()的dotenv_path参数,直接指定要加载的环境配置文件,想切换环境时,只需修改这一行的文件名称,适合本地调试、单人开发。
核心代码(main.py)
# 项目入口文件:main.pyfromdotenvimportload_dotenvimportos# 核心:指定加载的环境配置文件,切换环境只改这里!# 开发环境:load_dotenv(dotenv_path=".env.dev")# 测试环境:load_dotenv(dotenv_path=".env.test")# 生产环境:load_dotenv(dotenv_path=".env.prod")load_dotenv(dotenv_path=".env.dev")# 默认加载开发环境# 后续读取配置的逻辑完全不变,所有环境通用# 读取并转换配置(统一处理类型,避免各环境重复写)DB_URL=os.environ.get("DB_URL")DEBUG=os.environ.get("DEBUG")=="True"# 字符串转布尔LOG_LEVEL=os.environ.get("LOG_LEVEL","INFO")# 设默认值API_BASE_URL=os.environ.get("API_BASE_URL")# 测试配置加载if__name__=="__main__":print(f"当前环境:开发环境")print(f"数据库地址:{DB_URL}")print(f"调试模式:{DEBUG}")print(f"日志级别:{LOG_LEVEL}")切换环境
只需修改load_dotenv(dotenv_path="xxx")中的文件路径,比如要切生产环境,改为:
load_dotenv(dotenv_path=".env.prod")运行代码后,会自动加载生产环境的所有配置,无需修改其他读取配置的代码。
方案二:通过系统环境变量自动切换(行业最佳实践,适合团队/部署)
方案一需要手动改代码,不适合线上部署(总不能改代码切环境),更规范的方式是:在系统/部署环境中设置一个「环境标记变量」(比如ENV=prod、ENV=dev),代码中先读取这个标记,再自动加载对应名称的.env文件,实现「无代码修改,仅通过环境变量切换环境」。
这是企业开发的标准做法,支持本地开发、服务器部署、Docker容器等所有场景。
核心思路
- 定义环境标记变量:约定一个固定键名(比如
ENV、FLASK_ENV、FASTAPI_ENV),值为环境名(dev/test/prod); - 代码中先读取这个标记,判断当前是哪个环境;
- 根据环境名拼接对应配置文件路径(比如
ENV=prod→ 加载.env.prod); - 统一加载配置,后续读取逻辑不变。
核心代码(main.py)
封装了自动加载+配置统一转换的逻辑,可直接复用,后续新增环境只需加.env.新环境文件,无需改代码:
# 项目入口文件:main.pyfromdotenvimportload_dotenvimportosimportsysdefload_env():"""加载对应环境的配置文件,封装为函数,方便项目各处调用"""# 1. 读取系统环境中的「环境标记」,默认加载开发环境(本地调试友好)# 约定标记键名为 ENV,可自定义(比如 PROJECT_ENV)env=os.environ.get("ENV","dev")# 无标记时,默认dev# 2. 拼接配置文件路径(.env.dev/.env.test/.env.prod)dotenv_path=f".env.{env}"# 3. 检查配置文件是否存在,不存在则报错(避免加载空配置)ifnotos.path.exists(dotenv_path):print(f"错误:配置文件{dotenv_path}不存在!",file=sys.stderr)sys.exit(1)# 退出程序,避免配置缺失导致运行错误# 4. 加载配置文件load_dotenv(dotenv_path=dotenv_path,override=True)print(f"✅ 成功加载{env}环境配置:{dotenv_path}")# 项目启动时,最先执行配置加载(必须在所有业务代码之前)load_env()# 统一读取并转换配置(所有环境通用,一次封装,处处使用)# 注意:所有配置都做「非空校验+类型转换+默认值」,保证鲁棒性DB_URL=os.environ.get("DB_URL")ifnotDB_URL:raiseValueError("配置错误:DB_URL 未设置!")# 核心配置缺失直接报错DEBUG=os.environ.get("DEBUG","False")=="True"# 默认关闭调试LOG_LEVEL=os.environ.get("LOG_LEVEL","INFO").upper()# 统一大写(DEBUG/INFO/WARNING)API_BASE_URL=os.environ.get("API_BASE_URL","http://127.0.0.1:8000")# 测试配置if__name__=="__main__":print(f"数据库地址:{DB_URL}")print(f"调试模式:{DEBUG}")print(f"日志级别:{LOG_LEVEL}")print(f"接口地址:{API_BASE_URL}")关键:如何设置「环境标记变量 ENV」?
不同运行环境(本地终端、Windows/Mac、服务器、Docker)的设置方式不同,核心是在运行Python代码前,让系统能读取到ENV变量,下面讲最常用的场景:
场景1:本地开发(终端运行,Mac/Linux/Windows PowerShell)
在运行python main.py前,先在终端临时设置ENV变量,仅当前终端会话有效,关闭终端后失效(适合本地调试不同环境):
# Mac/Linux/Windows PowerShell - 设为开发环境(默认,可省略)exportENV=dev&&python main.py# 设为测试环境exportENV=test&&python main.py# 设为生产环境exportENV=prod&&python main.pyWindows CMD 终端语法略有不同:
# Windows CMD - 设为生产环境 set ENV=prod && python main.py场景2:本地永久设置(不想每次终端都输,适合个人开发)
可将ENV=dev写入系统环境变量,实现永久生效,不同系统设置方式:
- Mac/Linux:编辑
~/.bashrc或~/.zshrc,添加一行export ENV=dev,执行source ~/.zshrc生效; - Windows:此电脑 → 属性 → 高级系统设置 → 环境变量 → 新建系统变量,键
ENV,值dev,重启终端生效。
场景3:线上服务器部署(Linux/云服务器)
在服务器的启动脚本(比如start.sh)中设置ENV变量,启动项目时执行脚本即可,示例start.sh:
#!/bin/bash# 服务器启动脚本:设置为生产环境exportENV=prod# 启动Python项目(以FastAPI为例,其他项目同理)uvicorn main:app --host0.0.0.0 --port80赋予脚本执行权限并运行:
chmod+x start.sh ./start.sh场景4:Docker 部署(最常用的容器化方式)
在Dockerfile或docker-compose.yml中设置ENV变量,容器启动时自动加载,示例docker-compose.yml:
version:'3'services:app:build:.ports:-"80:80"# 设置环境标记:生产环境environment:-ENV=prodrestart:always方案三:生产环境优化(不加载 .env 文件,直接用系统环境变量)
线上生产环境的最佳实践是:不把.env.prod文件放到服务器(避免文件泄露),而是直接在服务器/容器中设置所有配置变量(比如 DB_URL、DEBUG 等),此时代码中只需跳过.env加载逻辑,直接读取系统环境变量即可。
基于方案二的代码,只需做简单修改,就能实现生产环境自动跳过 .env 加载,更安全:
defload_env():env=os.environ.get("ENV","dev")# 生产环境:不加载.env文件,直接读取系统环境变量ifenv=="prod":print("✅ 生产环境:直接读取系统环境变量")return# 非生产环境(dev/test):加载对应.env文件dotenv_path=f".env.{env}"ifnotos.path.exists(dotenv_path):print(f"错误:配置文件{dotenv_path}不存在!",file=sys.stderr)sys.exit(1)load_dotenv(dotenv_path=dotenv_path,override=True)print(f"✅ 成功加载{env}环境配置:{dotenv_path}")这样生产环境无需上传.env.prod,所有配置直接在服务器/Docker中设置,彻底避免敏感配置文件泄露。
补充:配置的统一管理(进阶技巧)
如果项目较大,配置分散在各处会不好维护,可将配置读取逻辑封装为单独的配置文件(比如settings.py),项目所有模块都从这里导入配置,实现单一入口。
示例:创建 settings.py(配置统一管理)
# settings.py:配置统一管理文件,项目所有模块都从这里导入fromdotenvimportload_dotenvimportosimportsys# 加载环境配置(复用之前的load_env函数)defload_env():env=os.environ.get("ENV","dev")ifenv=="prod":print("✅ 生产环境:读取系统环境变量")returndotenv_path=f".env.{env}"ifnotos.path.exists(dotenv_path):print(f"错误:{dotenv_path}不存在",file=sys.stderr)sys.exit(1)load_dotenv(dotenv_path=dotenv_path,override=True)print(f"✅ 加载{env}环境配置:{dotenv_path}")load_env()# 核心配置(非空校验+类型转换+默认值)# 数据库配置DB_URL=os.environ.get("DB_URL")ifnotDB_URL:raiseValueError("配置缺失:DB_URL 必须设置!")# 服务配置DEBUG=os.environ.get("DEBUG","False")=="True"LOG_LEVEL=os.environ.get("LOG_LEVEL","INFO").upper()API_BASE_URL=os.environ.get("API_BASE_URL","http://127.0.0.1:8000")# 服务器配置HOST=os.environ.get("HOST","0.0.0.0")PORT=int(os.environ.get("PORT",8000))项目中其他模块导入使用(简单便捷)
# main.py / 其他业务文件fromsettingsimportDB_URL,DEBUG,HOST,PORT# 直接使用配置,无需再处理加载/转换print(f"启动服务:{HOST}:{PORT},调试模式:{DEBUG}")print(f"数据库连接:{DB_URL}")# FastAPI示例fromfastapiimportFastAPI app=FastAPI(debug=DEBUG)if__name__=="__main__":importuvicorn uvicorn.run(app,host=HOST,port=PORT)核心总结(不同环境使用 python-dotenv 的关键)
- 配置隔离:为每个环境创建专属配置文件
.env.dev/.env.test/.env.prod,相同键名,不同值,保证环境隔离; - 两种切换方式:
- 本地开发用方案一:直接指定
dotenv_path加载文件,简单直观; - 团队/部署用方案二:设置系统环境标记
ENV,代码自动加载对应配置,无代码修改;
- 本地开发用方案一:直接指定
- 生产环境最佳实践:不使用
.env.prod文件,直接在服务器/容器中设置系统环境变量,代码中跳过.env加载,更安全; - 配置统一管理:封装
settings.py,将加载、转换、校验逻辑集中,项目所有模块统一导入,避免重复代码; - 必做操作:将
.env/.env.*加入.gitignore,只保留.env.example模板,防止敏感配置泄露。
这种方式适配所有Python项目(FastAPI/Flask/Django/爬虫等),是行业通用的环境配置管理方案,既灵活又规范。