环境变量优先级最高,覆盖配置文件——python应用启动时,环境变量(含动态赋值)总优先生效,配置文件仅作默认值;具体优先级由加载时机和顺序决定,非语言机制。

环境变量覆盖配置文件的规则很明确
Python 应用启动时,如果同一配置项既在 .env 或系统环境变量里定义,又在 config.py 或 settings.json 中声明,环境变量一定生效——这是由绝大多数主流加载逻辑(比如 python-decouple、pydantic-settings、Django 的 os.environ.get() 模式)默认实现的优先级决定的。
实操建议:
- 用
os.getenv("DEBUG")读取时,它不会回退到配置文件,必须手动 fallback,例如os.getenv("DEBUG", "False") -
python-decouple的Config实例默认就按“环境变量 > .env > 默认值”走,但注意:它不自动读config.py,那是另一个加载路径 - 如果你在
settings.py里写DEBUG = os.environ.get("DEBUG", False),那环境变量确实能覆盖,但一旦你改成DEBUG = True硬编码,环境变量就彻底失效了
配置文件之间没有天然优先级,全看你怎么 import
Python 本身不定义 config.py、settings.toml、pyproject.toml 谁高谁低。所谓“开发/测试/生产配置分离”,其实是靠运行时 import 顺序或条件判断实现的,不是语言机制。
常见错误现象:
立即学习“Python免费学习笔记(深入)”;
PHP商城系统是国内领先商城系统,网店系统,购物系统,网上商城系统,B2C商城系统产品.同时也是一个商业的PHP开发框架。PHP 商城系统由内容、文章、会员、留言、订单、 财务、广告、短消息、数据库管理、营销推广、内置支付管理、商品配送管理、无限级分类、全站搜索等多个功能模块插件组成。在当今瞬机万变的市场环境中,快速高效的IT解决方案是您业务成功的关键。我们PHP商城系统能为您量身打造完全符合需求
- 在
__init__.py里直接from config import *,结果不同环境跑的却是同一个文件,因为没做if os.getenv("ENV") == "prod"分支 - 用
importlib.import_module(f"config.{os.getenv('ENV', 'dev')}")动态导入,但忘了处理模块不存在异常,导致启动失败而不是降级 -
pydantic-settings支持多源合并(如.env+settings.yaml),但它把环境变量当作最高优先级源,配置文件只是“默认值提供者”,不是中间层
配置中心(如 Consul / Apollo)本质是远程环境变量
接入配置中心后,你的应用通常会启动时拉取键值对并注入 os.environ,或者封装成类似 config.get("DB_URL") 的接口。它不改变“环境变量 > 配置文件”的层级关系,只是把环境变量的来源从本地移到了远端。
性能与兼容性影响:
- 首次启动会增加几百毫秒延迟(取决于网络和中心响应),之后一般有本地缓存,但缓存失效策略要自己控制
- 如果配置中心不可用且没设 fallback,应用可能启动失败;建议用
try/except包住拉取逻辑,退回到读本地.env - Apollo 的 Python SDK 默认把远端配置转为
os.environ,所以它天然压过config.py;Consul 客户端则多数需要你手动调os.environ.update(...)
三级优先级不是静态树,而是加载时机决定的
真正起作用的是“谁最后写入内存里的配置对象”。比如你在 app.py 开头读 .env,中间 import config.py,结尾再执行 load_from_consul() 并覆盖字段——那最终生效的就是 Consul 的值。
容易被忽略的点:
- Django 的
settings.py是模块级执行,一旦导入完成,后续改os.environ不会影响已解析的DEBUG或DATABASES - FastAPI 的
BaseSettings类在实例化时才读环境变量,所以你可以先改os.environ再初始化它,实现运行时切换 - 很多项目把“环境变量”理解为仅指 shell 启动时的
export,其实os.environ["FOO"] = "bar"在代码里任何位置赋值都算,只是时机决定它能否被后续加载逻辑捕获









