核心篇 · Core
lv.2 核心
kp-021
虚拟环境与依赖管理
1. 一句话定义
虚拟环境(venv)为每个项目提供独立的解释器视图 + 独立的第三方包目录;依赖声明进 pyproject.toml,锁定版本生成 lock 文件——这是 Python 项目可复现的最小闭环。
2. 为什么重要
"项目 A 要 requests 2.x、项目 B 要 3.x"在同一解释器下不可解。虚拟环境把依赖隔离到项目级,是所有现代工具(uv/poetry/pipenv)共同的底层思想。
3. 前置知识
kp-002(解释器与 PATH)、kp-014(模块查找)。
4. 核心概念
- venv 目录:
python3 -m venv .venv生成;内含指向基础解释器的链接 + 独立site-packages。 - 激活:
source .venv/bin/activate把.venv/bin排到 PATH 首位(deactivate退出)。 - pip 闭环:
pip install→ 写入环境 +pip freeze > requirements.txt。 - pyproject.toml(PEP 621):项目元数据 + 依赖声明的标准文件,取代旧
setup.py。 - uv(现代首选):
uv add、uv sync、uv.lock,比 pip 快一个数量级且自动管理 venv。
5. 原理与机制
bash
# 传统 pip 流程
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install requests
pip freeze > requirements.txt # 快照当前环境(含间接依赖)
pip install -r requirements.txt # 复现
# uv 流程(推荐)
uv init # 生成 pyproject.toml
uv add requests # 声明 + 安装 + 更新 lock
uv sync # 按 lock 精确重建环境
uv run python script.py # 无需手动激活venv 的本质:.venv/bin/python 是一个会优先查 .venv/lib/pythonX.Y/site-packages 的解释器入口—— kp-014 的 sys.path 多了一条项目专属路径而已。
6. 关键事实(模型/图示)
text
系统解释器 ──共享──► /usr/lib/python3/site-packages ← 别动
│
└── .venv/ ──► .venv/lib/.../site-packages ← 项目专属
↑ pip/uv 只写这里
依赖三层概念:
声明(pyproject: 我需要 requests>=2)→ 锁定(uv.lock: 2.32.3 具体版本)
→ 安装(site-packages 里的实际代码)7. 直观类比
虚拟环境是每道菜的独立料理台:砧板调料互不串味(依赖隔离);pyproject.toml 是菜谱(用什么料),lock 是采购单(哪个牌子哪一批次),照单采购(sync)才能做出一模一样的菜。
8. 实例与案例
bash
# 排查"装了却 import 不到"
which python3 # 用的是哪个解释器?
python3 -c "import sys; print(sys.prefix)" # 是否在 .venv 里
pip show requests # 装到了哪个 site-packages三连问能解决 90% 的"环境玄学"。
9. 常见误区
- 激活了 A 项目环境却在 B 项目工作 —— 检查提示符前缀
( .venv );或干脆用uv run避免手动激活。 - 只提交 requirements 不提交 lock ——
freeze快照与lock解析可复现是两码事;团队/CI 用锁定文件。 - 把
.venv提交进 git —— 它含平台相关二进制;.gitignore掉。 - 直接
pip install进系统/Conda base —— PEP 668 后新版发行版会拒绝(externally-managed-environment);本来就该隔离。
10. 自测题
- venv 里
import requests能找到包的完整链路是什么? requirements.txt与uv.lock的本质区别?- "装了却 import 不到"的三步排查?
参考答案
- 当前 python 的 sys.path 指向 .venv 的 site-packages → 该目录里有 requests → 正常导入;反之若解释器不在 .venv,则查的是别的 site-packages。
- freeze 是"当前环境快照"(环境相关、顺序无保证);lock 是"依赖解析的确定性结果"(跨平台可复现、含哈希)。
- 见实例与案例:which / sys.prefix / pip show。
11. 与其他知识点的关系
12. 延伸阅读
- Python Packaging User Guide(virtualenvs 章节)
- uv 文档:https://docs.astral.sh/uv/concepts/projects/