支持自动加载.env并补充环境变量模板

- 为 configuration.py 增加项目根目录 .env 自动加载能力,启动时无需再手动 export\n- 新增 .env.example,补齐数据库、Redis、邮件、LLM 与后台 secret 等完整环境变量模板\n- 更新 .gitignore 与 README,明确 .env 的使用方式与优先级说明
This commit is contained in:
liuwei
2026-04-30 15:49:37 +08:00
parent c6d72cbb69
commit 97fc6dc2a4
4 changed files with 112 additions and 5 deletions

View File

@@ -42,6 +42,11 @@ class Config(object):
def __init__(self, config_path: str = None) -> None:
self.project_dir = os.path.dirname(os.path.abspath(__file__))
self.config_path = config_path or os.path.join(self.project_dir, "config.yaml")
# 启动阶段优先尝试自动加载项目根目录下的 `.env`
# 1. 用户只需要把 `.env` 放到线上目录,不必每次手动 export
# 2. 这里刻意保持“已有系统环境变量优先”,避免覆盖运维层显式注入的值;
# 3. 不额外引入第三方依赖,保持部署门槛尽量低。
self._load_local_env_file(os.path.join(self.project_dir, ".env"))
self.raw_config = {}
self.resolved_config = {}
self.unresolved_placeholders = []
@@ -54,6 +59,50 @@ class Config(object):
yconfig = yaml.safe_load(fp) or {}
return yconfig
@staticmethod
def _strip_optional_quotes(value: str) -> str:
"""去掉 `.env` 中常见的首尾引号。"""
text = str(value or "").strip()
if len(text) >= 2 and text[0] == text[-1] and text[0] in {"'", '"'}:
return text[1:-1]
return text
def _load_local_env_file(self, env_path: str) -> None:
"""从本地 `.env` 文件加载环境变量。"""
if not os.path.exists(env_path):
return
try:
with open(env_path, "r", encoding="utf-8") as env_file:
for raw_line in env_file:
line = str(raw_line or "").strip()
if not line or line.startswith("#"):
continue
# 兼容 `export KEY=value` 写法,方便 Linux 用户直接复用 shell 风格文件。
if line.startswith("export "):
line = line[len("export "):].strip()
if "=" not in line:
continue
key, value = line.split("=", 1)
key = str(key or "").strip()
value = self._strip_optional_quotes(value)
if not key:
continue
# `.env` 只在“当前进程还没有这个变量”时兜底注入:
# 1. 显式传入的系统环境变量优先级更高;
# 2. 这样本地调试和线上运维都可以覆盖 `.env` 默认值;
# 3. 也避免启动时误把运维平台上的密钥覆盖掉。
if key not in os.environ:
os.environ[key] = value
except Exception:
# `.env` 自动加载属于增强能力,不应因为格式问题直接把启动打死。
# 真正的必填项缺失会在后续 validate 阶段给出明确错误。
return
def _resolve_env_placeholders_in_string(self, raw_value: str, path: str) -> str:
"""解析字符串中的环境变量占位符。"""