01使用 pip 与 uv 管理 Python 环境和依赖

区分 package installer、virtual environment 与 project dependency management,并分别使用 pip/venv 和 uv 建立可复现的 Python 项目。

2025-10-16
PythonpipuvVirtual EnvironmentsDependency Management
本章目录 · 22

安装一个 Python package 看起来只需要一条命令,但项目真正涉及三件事:使用哪个 Python interpreter、把 packages 安装到哪个隔离环境,以及怎样记录并重建依赖版本。

pipuv 都能安装 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.tomluv.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 installuv 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.txtuv.lock 是否相同

不是。requirements file 是 pip 能读取的依赖输入格式,也可以包含精确 pin;uv.lock 是 uv project resolver 维护的完整锁定结果,并与 pyproject.toml 配套。

能否混用 pip 与 uv

技术上可以,但在受 lockfile 管理的环境中直接运行 pip 会使实际环境与锁定状态漂移。uv project 中优先使用 uv adduv removeuv 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 减少重复操作。

参考:pip documentationuv documentationPEP 621