
.env 文件不应随 Python 包一起打包分发,尤其当其包含敏感信息(如 API 密钥、数据库凭证);正确做法是将配置外置,通过文档引导用户本地创建,并利用 python-dotenv 或 pydantic-settings 在运行时加载环境变量。
`.env` 文件不应随 python 包一起打包分发,尤其当其包含敏感信息(如 api 密钥、数据库凭证);正确做法是将配置外置,通过文档引导用户本地创建,并利用 `python-dotenv` 或 `pydantic-settings` 在运行时加载环境变量。
在 Python 包开发与分发实践中,.env 文件常被误认为是“配置资源”,应随代码一并打包。但事实恰恰相反:.env 是运行时配置文件,属于部署/使用阶段的用户责任,而非构建/分发阶段的包内容。将其纳入 pyproject.toml 构建流程或发布到 PyPI,不仅违反安全原则,也破坏了 Python 包的可复现性与环境隔离性。
✅ 正确做法:分离配置与代码
-
不打包 .env
确保 .env 文件被明确排除在分发包之外:- 在 pyproject.toml 的 [project] 或 [tool.setuptools] 配置中不声明 .env;
- 将其加入 .gitignore 和 MANIFEST.in 的 global-exclude(若使用);
- 使用 setuptools 的 package-data 或 include-package-data = false 默认策略,避免意外包含。
# pyproject.toml —— 无需特殊配置,.env 默认不被包含 [build-system] requires = ["setuptools>=61.0", "wheel"] build-backend = "setuptools.build_meta" [project] name = "my-awesome-tool" version = "0.1.0" # ❌ 不要写:data-files = [".env"] 或 include = ["*.env"]
-
运行时按需加载(推荐方案)
使用 python-dotenv 安全读取本地 .env(仅在开发/本地执行时生效),同时兼容系统环境变量(适用于生产部署):# mypackage/config.py from dotenv import load_dotenv import os # 自动查找并加载项目根目录下的 .env(不递归,不打包) load_dotenv() # ← 此行只在运行时执行,不参与构建 class Config: DATABASE_URL = os.getenv("DATABASE_URL", "sqlite:///default.db") API_KEY = os.getenv("API_KEY") # None if missing → 可触发校验逻辑? 提示:load_dotenv() 默认只加载当前工作目录或父级目录中的 .env,不会读取安装路径(如 site-packages),因此即使误打包也无风险。
-
进阶推荐:Pydantic Settings(类型安全 + 多源支持)
若追求健壮性与开发体验,pydantic-settings 是现代首选——它原生支持 .env、系统 ENV、默认值、类型校验及嵌套配置:# mypackage/settings.py from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): database_url: str = "sqlite:///dev.db" api_key: str debug: bool = False model_config = SettingsConfigDict( env_file=".env", # 优先读取同级 .env env_file_encoding="utf-8", extra="ignore" ) settings = Settings() # 自动合并 .env + OS 环境变量安装依赖只需在 pyproject.toml 中声明:
[project.dependencies] pydantic-settings = ">=2.0"
⚠️ 关键注意事项
- 绝不硬编码或提交敏感值:.env 必须在版本控制中忽略(.gitignore 中添加 *.env、.env.*);
-
提供清晰文档与模板:在 README.md 中附 .env.example 并说明字段用途,例如:
# .env.example —— 复制为 .env 并填写实际值 DATABASE_URL=postgresql://user:pass@localhost/db API_KEY=sk_live_...
- 云环境适配:CI/CD 或容器化部署(Docker/K8s)应直接注入环境变量,跳过 .env 文件(docker run -e API_KEY=...);
- setup.py vs pyproject.toml 无关性:.env 处理逻辑完全独立于构建工具——无论用 setuptools、poetry 还是 hatch,都不应将其纳入构建产物。
✅ 总结
| 场景 | 推荐做法 |
|---|---|
| 本地开发调试 | 用户自行创建 .env,代码中 load_dotenv() 加载 |
| 生产部署(服务器/云) | 通过系统环境变量注入,.env 文件不参与部署 |
| 包分发(PyPI / wheel) | 绝对不包含 .env,确保 dist/ 目录纯净 |
| 配置验证与提示 | 使用 pydantic-settings 实现缺失必填项报错、类型强制转换 |
遵循此模式,你的包将更安全、更专业、更易被他人集成——因为真正的配置自由,永远属于使用者,而非包作者。
立即学习“Python免费学习笔记(深入)”;


















