安装一个 Python package 看起来只需要一条命令,但项目真正涉及三件事:使用哪个 Python interpreter、把 packages 安装到哪个隔离环境,以及怎样记录并重建依赖版本。
pip 与 uv 都能安装 Python packages,但它们的职责范围不同:
pip是 Python 生态的标准 package installer,通常与venv、requirements files 和其他工具组合使用;uv同时覆盖 Python versions、virtual environments、package installation、dependency resolution、lockfile 与 project commands。
因此,uv add pandas 不是简单把 pip install pandas 换成更快的拼写;它还会把 pandas 记录为项目依赖,并更新 lockfile。
先分清四层状态
| 层次 | 回答的问题 | 常见工具或文件 |
|---|---|---|
| Python interpreter | 代码由哪个 Python 版本运行? | python, uv python |
| Virtual environment | packages 安装到哪个隔离环境? | venv, .venv/, uv venv |
| Declared dependencies | 项目声明需要哪些 packages? | pyproject.toml, requirements.txt |
| Resolved environment | 每个直接与间接依赖最终使用什么版本? | uv.lock, pinned requirements |
很多“已经安装却 import 不到”的问题,实际是运行代码的 interpreter 与执行安装命令的 interpreter 不同。
检查当前 Python 与 pip:
python --version
python -m pip --version
使用 python -m pip 比直接运行 pip 更明确,因为它把 pip 绑定到当前这一个 Python interpreter。
pip + venv 工作流
创建虚拟环境
python -m venv .venv
激活环境。
Windows PowerShell:
.\.venv\Scripts\Activate.ps1
macOS / Linux:
source .venv/bin/activate
激活后再次确认:
python --version
python -m pip --version
pip 输出中的安装位置应该指向当前 .venv。
安装 packages
python -m pip install requests pandas
查看已安装版本:
python -m pip list
python -m pip show pandas
导出与恢复 requirements
python -m pip freeze > requirements.txt
另一台机器创建新环境后:
python -m pip install -r requirements.txt
pip freeze 记录当前环境中直接和间接安装的 packages。它能产生版本快照,但不会说明哪些是项目直接依赖,也不会自动维护 pyproject.toml 中的项目元数据。
一个 requirements file 可以固定版本:
requests==2.32.3
pandas==2.2.3
也可以配合 hashes 进行更严格的安装校验,但生成和更新这些约束通常需要额外工作流。pip 的核心职责仍是安装,不是统一管理项目生命周期。
退出环境
deactivate
虚拟环境目录通常不提交到 Git:
.venv/
提交的是依赖声明或锁定文件,让环境能够重建,而不是复制本机环境目录。
uv 的两种使用方式
uv 同时提供 pip-compatible commands 和 project workflow。两者解决的问题不同。
作为更快的 pip/venv 接口
创建环境:
uv venv
安装 requirements:
uv pip install -r requirements.txt
临时使用 uv 加速旧项目时,这种方式不要求把项目立即改成 uv project。
作为项目管理器
初始化项目:
uv init myproject
cd myproject
添加依赖:
uv add requests pandas
uv 会更新 pyproject.toml 中的项目依赖,并生成或更新 uv.lock。
运行脚本:
uv run python script.py
同步环境:
uv sync
典型项目结构:
myproject/
├─ .venv/
├─ pyproject.toml
├─ uv.lock
├─ .python-version
└─ main.py
具体文件会随初始化选项和项目类型不同而变化,但职责保持一致:pyproject.toml 声明项目,uv.lock 固定解析结果,.venv 保存本机环境。
pyproject.toml 与 uv.lock
一个简化的项目声明:
[project]
name = "myproject"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
"pandas>=2.2",
"requests>=2.32",
]
这里声明的是项目允许的依赖范围。uv.lock 则保存解析后的具体依赖图,用于在不同机器上建立一致环境。
日常规则可以简化为:
- 手工维护项目意图时看
pyproject.toml; - 让 uv 生成和更新
uv.lock; - 将两者提交到版本控制;
- 不手工编辑
.venv; - 团队用
uv sync根据 lockfile 重建环境。
pip 与 uv 命令对照
| 任务 | pip / venv | uv project |
|---|---|---|
| 创建环境 | python -m venv .venv |
uv venv 或由项目命令管理 |
| 安装单个 package | python -m pip install pandas |
uv add pandas |
| 删除项目依赖 | python -m pip uninstall pandas,并手工更新声明 |
uv remove pandas |
| 根据 requirements 安装 | python -m pip install -r requirements.txt |
uv pip install -r requirements.txt |
| 运行脚本 | 激活环境后 python script.py |
uv run python script.py |
| 记录当前环境 | pip freeze |
uv.lock |
| 同步项目环境 | 重新安装 requirements | uv sync |
uv pip install 与 uv add 也不能混为一谈:前者更接近 pip-compatible installation,后者修改 project dependency declaration。
从 pip 项目迁移到 uv
已有 requirements.txt 时,不必一次性重写所有内容。
先直接使用兼容接口验证环境:
uv venv
uv pip install -r requirements.txt
确认项目能够运行后,再决定是否采用 pyproject.toml 与 lockfile workflow。迁移时区分:
- 哪些 packages 是项目直接依赖;
- 哪些只是间接依赖;
- 哪些只用于开发、测试或文档;
- Python version 是否需要固定;
- 是否依赖私有 index、Git repository 或本地 package。
不要把 pip freeze 的每一行都不加判断地当作顶层依赖。这样虽然可能暂时重建环境,却会让项目声明充满不必要的间接 packages。
什么时候使用哪一种
pip + venv 更合适
- 学习 Python packaging 的基础组成;
- 维护已经稳定使用 requirements files 的项目;
- 系统环境只提供标准 Python 工具;
- 需要与既有部署流程完全保持一致;
- 只进行一次性、范围很小的环境测试。
uv 更合适
- 新建需要长期维护的 Python 项目;
- 希望统一 Python、virtual environment、dependencies 和 commands;
- 需要 lockfile 重建开发环境;
- 频繁创建环境或安装大型依赖树;
- 希望减少 pip、venv 与额外项目管理工具之间的手工衔接。
选择 uv 不意味着 pip 生态失效。uv 继续使用 Python packaging standards、package indexes 与既有 distribution formats;区别主要在解析、缓存、项目状态和操作体验。
性能结果怎样看
原笔记在 macOS M2、Python 3.12 与同一 PyPI source 下记录过以下用时:
| 操作 | pip | uv 0.3.x |
|---|---|---|
| 安装 pandas + numpy | 10.8 s | 1.7 s |
| 安装 matplotlib + seaborn | 12.2 s | 2.3 s |
| 再次安装(使用缓存) | 7.2 s | 0.3 s |
这些数字只描述那次机器、网络、缓存和工具版本,不能作为所有项目的固定倍率。比较时至少应控制 Python version、package index、环境是否为空、网络状态和缓存冷热。
性能是 uv 的明显优势,但长期项目更重要的变化是:依赖声明、解析结果、环境同步与命令运行由同一套 project model 管理。
常见问题
安装成功但 import 失败
检查安装和运行是否使用同一个 interpreter:
python -c "import sys; print(sys.executable)"
python -m pip --version
uv 项目中可以直接:
uv run python -c "import sys; print(sys.executable)"
是否需要激活 uv 的 .venv
可以激活后使用普通 python,也可以不激活而统一通过 uv run 执行。团队应选择一种清楚且一致的方式。
requirements.txt 和 uv.lock 是否相同
不是。requirements file 是 pip 能读取的依赖输入格式,也可以包含精确 pin;uv.lock 是 uv project resolver 维护的完整锁定结果,并与 pyproject.toml 配套。
能否混用 pip 与 uv
技术上可以,但在受 lockfile 管理的环境中直接运行 pip 会使实际环境与锁定状态漂移。uv project 中优先使用 uv add、uv remove 和 uv sync;兼容旧 requirements workflow 时再使用 uv pip。
最小选择
只想临时创建隔离环境:
python -m venv .venv
python -m pip install package-name
开始一个需要长期维护的新项目:
uv init myproject
cd myproject
uv add package-name
uv run python main.py
学习时值得同时理解 pip、venv、requirements 和 pyproject.toml,因为它们解释了 Python packaging 的基础结构;实际新项目则可以让 uv 减少重复操作。