pip 与虚拟环境 venv

学 Python 的人几乎都会踩这两个坑:

  1. 依赖冲突:A 项目要 numpy==1.20,B 项目要 numpy==1.25,两个项目一起装到系统 Python 里,A 用起来 B 就崩;
  2. 环境污染:随手 pip install 装了 100 多个包,之后不知道哪个是哪个项目要的,也不敢删。

答案就是 虚拟环境(venv)——每个项目一个独立的 Python 依赖沙箱。配合 pip,你能优雅地管理任意多个项目的依赖。这一篇讲透 pip、venv、requirements.txt、pyproject.toml,以及现代化的替代品(uv、poetry)。

一、pip 是什么

pip 是 Python 官方推荐的包管理工具,用来安装、升级、卸载第三方库。Python 3.4+ 自带 pip。

1
2
pip --version
python -m pip --version # 更保险,明确用当前 Python 的 pip

二、pip 常用命令

安装 / 卸载 / 升级

1
2
3
4
5
6
7
8
pip install requests                # 装最新版
pip install requests==2.31.0 # 指定版本
pip install "requests>=2.28" # 版本范围
pip install "requests[security]" # 装 extras
pip install -r requirements.txt # 从需求文件批量装

pip install -U requests # 升级
pip uninstall requests # 卸载

查询

1
2
3
4
pip list                    # 已安装的包
pip show requests # 详情
pip freeze # 用于生成 requirements.txt
pip search xxx # 已废弃,用 https://pypi.org 网页搜

换源

pip 默认从 PyPI 下载,国内速度慢。换成清华源:

1
2
3
4
5
# 一次性
pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple

# 全局设置
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

三、为什么需要虚拟环境

没有虚拟环境的世界

1
2
pip install django==3.2      # 项目 A 用
pip install django==4.2 # 项目 B 用 → 装完 A 就崩了

系统只有一个 Python,装到里面就冲突。

有虚拟环境的世界

1
2
项目 A/.venv/  ← django 3.2
项目 B/.venv/ ← django 4.2

每个项目独立,互不干扰。

四、venv:官方虚拟环境工具

Python 3.3+ 自带 venv,无需安装。

创建

在项目根目录:

1
2
3
4
5
# Windows
python -m venv .venv

# macOS/Linux
python3 -m venv .venv

会创建一个 .venv/ 目录,里面装着一份独立的 Python 解释器和标准库链接。

激活

激活后当前 shell 的 python/pip 都指向这个虚拟环境:

1
2
3
4
5
6
7
8
# Windows PowerShell / cmd
.venv\Scripts\activate

# Windows Git Bash
source .venv/Scripts/activate

# macOS/Linux
source .venv/bin/activate

激活后命令提示符前会多出 (.venv)

1
(.venv) $ pip install requests

退出

1
deactivate

删除虚拟环境

直接删掉整个 .venv/ 目录即可,没有其他”注册”要清理。

五、requirements.txt:项目依赖清单

记录依赖:

1
pip freeze > requirements.txt

生成的文件类似:

1
2
3
4
5
certifi==2024.2.2
charset-normalizer==3.3.2
idna==3.6
requests==2.31.0
urllib3==2.2.1

恢复依赖(在别人的电脑或另一个虚拟环境):

1
pip install -r requirements.txt

freeze 的问题

pip freeze 把间接依赖(依赖的依赖)也列了出来,太啰嗦。更规范的做法:

  • 顶层依赖写在 requirements.txt(只写你直接用的);
  • 锁定所有版本写在 requirements-lock.txt(由 pip freeze 或 pip-tools 生成,用来重现环境)。

或者用现代工具 pip-tools

1
2
3
4
5
6
7
8
pip install pip-tools
# requirements.in(人写)
requests
pandas>=2.0

# 生成锁文件
pip-compile requirements.in # → requirements.txt(含所有依赖)
pip-sync requirements.txt # 同步环境

六、pyproject.toml:现代项目配置

requirements.txt 太朴素,现代 Python 用 pyproject.toml 一站式描述项目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[project]
name = "myapp"
version = "0.1.0"
requires-python = ">=3.10"
dependencies = [
"requests>=2.28",
"pydantic~=2.0",
]

[project.optional-dependencies]
dev = ["pytest", "black", "mypy"]

[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

然后:

1
2
pip install -e .              # 装项目本身
pip install -e ".[dev]" # 带上 dev 依赖

七、常用第三方工具

uv(Rust 写的极速 pip 替代品,2024 起流行)

1
2
3
pip install uv
uv venv # 一秒创建虚拟环境
uv pip install -r requirements.txt # 比 pip 快 10-100 倍

poetry

以前很火的项目管理器,功能全但配置繁琐。新人可以先跳过。

conda(Anaconda)

科学计算/AI 生态用得多,能装 non-Python 依赖(C 库、CUDA 等)。用 conda 就别混用 pip,容易乱。

八、pipx:全局安装 CLI 工具

有些命令行工具(blackruffipythonawscli)你希望全局可用独立环境

1
2
pipx install black
pipx install ruff

pipx 会为每个工具建一个隐藏虚拟环境,暴露一个命令,互不干扰。

九、依赖版本约束语法

1
2
3
4
5
6
7
requests            # 任意版本
requests==2.31.0 # 精确
requests>=2.28 # 大于等于
requests~=2.28.0 # 兼容版本:2.28.* 都行,不含 2.29
requests<3 # 小于
requests>=2.28,<3 # 组合
requests!=2.29.0 # 不等于

~=语义化版本的推荐写法——允许”补丁号”升级,禁止”次版本号”变化。

十、常见工作流

新项目

1
2
3
4
5
6
mkdir myproject && cd myproject
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install --upgrade pip
pip install requests pandas
pip freeze > requirements.txt

别人的项目

1
2
3
4
5
git clone <url>
cd <repo>
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

IDE 里挑选解释器

  • VS Code:Ctrl+Shift+P → “Python: Select Interpreter” → 选 .venv/bin/python
  • PyCharm:Settings → Python Interpreter → Add → Existing Environment。

十一、.gitignore 里加什么

永远不要把虚拟环境目录、缓存、编译产物提交进 git:

1
2
3
4
5
.venv/
__pycache__/
*.pyc
.pytest_cache/
.mypy_cache/

十二、镜像源与私有源

全局设置镜像

1
2
3
4
5
6
# Linux/macOS: ~/.pip/pip.conf
# Windows: %APPDATA%\pip\pip.ini

[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
trusted-host = pypi.tuna.tsinghua.edu.cn

项目级镜像

在项目根目录放 pip.conf,只在这个项目里生效。

私有 PyPI(企业内网)

1
pip install --extra-index-url https://pypi.company.com/simple mypkg

十三、依赖冲突诊断

pip install 有时候会报 “cannot resolve dependencies” 或者装完运行时报导入错误。诊断步骤:

  1. pip list 查看已装的版本;
  2. pip show <包名> 查看依赖关系;
  3. pip check 让 pip 检查依赖冲突;
  4. pipdeptree 看依赖树:
1
2
3
pip install pipdeptree
pipdeptree # 打印所有依赖树
pipdeptree -w silence # 只显示冲突

十四、一个完整例子:搭建 Web 项目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 1. 建立虚拟环境
mkdir myweb && cd myweb
python -m venv .venv
source .venv/bin/activate

# 2. 装依赖
pip install --upgrade pip
pip install fastapi uvicorn[standard]

# 3. 写代码
cat > main.py << 'EOF'
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def hello():
return {"msg": "hello 咖飞"}
EOF

# 4. 运行
uvicorn main:app --reload

# 5. 保存依赖
pip freeze > requirements.txt

# 6. 提交前的 .gitignore
cat > .gitignore << 'EOF'
.venv/
__pycache__/
*.pyc
EOF

一个新同事拿到你的仓库,只需要:

1
2
3
4
5
git clone <repo> && cd myweb
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn main:app

就能跑起来。

十五、常见陷阱

  1. 忘记激活虚拟环境pip install 装到系统 Python 了。永远看命令提示符前是否有 (.venv)
  2. 多个 Python 版本共存pip 有时装到别的 Python 上。用 python -m pip install ... 强制绑定到当前 python。
  3. 在 requirements.txt 里锁到过旧版本:不主动升级容易积累技术债,也可能有安全漏洞。定期 pip list --outdated 检查。
  4. 虚拟环境跨机器复制.venv/ 有硬编码路径,不能复制到别的电脑。永远靠 requirements.txt 重建。
  5. conda 和 pip 混用:容易乱。选一个坚持用。
  6. 用 sudo pip install:Linux 上千万别 sudo,会污染系统 Python。永远用虚拟环境。

十六、小结与延伸阅读

  • 每个项目一个虚拟环境,永远不要污染系统 Python;
  • python -m venv .venv 创建,source .venv/bin/activate 激活;
  • pip installpip freezepip install -r requirements.txt 三剑客;
  • pyproject.toml 描述项目;
  • 想更快用 uv,想更完善用 poetry
  • CLI 工具用 pipx
  • 别把 .venv/ 提交进 git。

延伸阅读:

到这里模块三(函数与模块)7 篇结束! 下一篇进入 模块四:面向对象编程,从 类与对象基础 开始。