
UV 不直接修改虚拟环境的激活脚本(如 activate)来持久化环境变量,而是通过 uv run --env-file 或 UV_ENV_FILE 环境变量机制,在运行时按需注入变量,兼顾安全性、可复现性与项目隔离性。
uv 不直接修改虚拟环境的激活脚本(如 `activate`)来持久化环境变量,而是通过 `uv run --env-file` 或 `uv_env_file` 环境变量机制,在运行时按需注入变量,兼顾安全性、可复现性与项目隔离性。
在使用 UV 创建的虚拟环境中,不推荐也不支持通过手动编辑 .venv/Scripts/activate(Windows)或 .venv/bin/activate(macOS/Linux)等激活脚本来设置环境变量——这不仅违背 UV 的“无状态、可复现”设计哲学,还可能导致跨平台行为不一致、CI/CD 流水线失败,甚至被 uv sync 或 uv venv --clone 等操作覆盖。
UV 提供了更现代、更可靠的方式:运行时环境变量注入。其核心机制是将环境变量声明解耦至独立配置文件(如 .env),并在执行命令时显式加载,确保变量仅作用于当前进程,不污染 shell 会话,且天然兼容 Docker、CI 和多环境部署。
✅ 正确做法:使用 --env-file 或 UV_ENV_FILE
1. 创建环境变量文件(推荐 .env)
在项目根目录创建 .env 文件(注意:该文件应加入 .gitignore,避免敏感信息泄露):
# .env DEBUG=true DATABASE_URL=sqlite:///dev.db API_KEY=sk_abc123 # ⚠️ 仅用于本地开发,切勿提交!
2. 运行时加载变量(两种等效方式)
方式一:命令行显式指定(推荐,清晰可审计)
uv run --env-file=.env python main.py # 或运行带参数的脚本 uv run --env-file=.env uvx httpx https://httpbin.org/get
方式二:全局设定 UV_ENV_FILE(适合团队统一约定)
# Linux/macOS export UV_ENV_FILE=.env uv run python main.py # Windows (PowerShell) $env:UV_ENV_FILE=".env" uv run python main.py
? 提示:
UV_ENV_FILE可设为任意路径(如./config/local.env),支持多级嵌套加载(需配合dotenv库解析,UV 本身仅负责读取并注入os.environ)。
3. 高级场景:条件化变量注入
结合 pyproject.toml 中的 [tool.uv.run] 配置,实现不同命令的差异化变量加载:
# pyproject.toml
[tool.uv.run]
dev = { cmd = "python main.py", env-file = ".env.dev" }
prod = { cmd = "gunicorn app:app", env-file = ".env.prod" }然后执行:
uv run dev # 自动加载 .env.dev uv run prod # 自动加载 .env.prod
⚠️ 注意事项与最佳实践
-
不修改激活脚本:
.venv/bin/activate是 UV 自动生成的轻量包装器,手动编辑易被覆盖,且无法保证uv run命令生效(因uv run绕过 shell 激活逻辑); -
变量作用域严格限定:
--env-file注入的变量仅对uv run启动的子进程有效,退出后自动清除,杜绝“变量残留”导致的调试陷阱; -
优先级规则:命令行
--env-file>UV_ENV_FILE环境变量 > 系统默认环境变量; -
安全第一:永远将
.env加入.gitignore;生产环境应通过 Kubernetes Secrets、AWS Parameter Store 等安全服务注入,而非文件; -
验证是否生效:可在脚本中快速验证:
# verify_env.py import os print("DEBUG =", os.getenv("DEBUG")) print("DATABASE_URL =", os.getenv("DATABASE_URL"))执行:
uv run --env-file=.env python verify_env.py
UV 的这一设计,正是其区别于传统工具的关键:它不试图“永久污染”环境,而是以最小侵入、最大可控的方式,让环境变量成为可版本化、可审计、可组合的一等公民。对于追求工程化交付的 Python 团队,这是从“能跑”迈向“稳跑”的重要一步。

















