装包只有一条命令 pip install,麻烦的是「装哪个版本、装到哪去、以后怎么复原」。
Demo 列出当前环境 91 个已装包,
再用一份五行清单去核对——
numpy 2.5.2 满足、pyyaml 6.0.3 满足、matplotlib 3.11.1 满足,pandas 和 torch 根本没装,
五个只过三个。 最后一段讲清楚为什么推荐写 python -m pip 而不是 pip。
上一节建好了空的虚拟环境,这一节往里装东西。 这是全书最后一个小节,也是实操里最高频的动作——2.x 节的 numpy、4.2 节的 TF-IDF、 图像任务的 Pillow,全靠这一步。装包装错地方,是新手最常见的时间黑洞。
一、三条命令,从简到繁
最简单:pip install 包名。装最新版。
指定版本:pip install 包名==2.5.2。复现别人的环境时用。
按清单装:python -m pip install -r requirements.txt。真实项目的标准做法。
装完想确认:pip list 看全部、pip show 包名 看单个的详情(版本、依赖、装在哪)、
pip freeze 输出一份可以直接当 requirements.txt 用的清单。
pip freeze 是「我这环境到底有什么」的权威答案。
二、requirements.txt 的四种写法
numpy:任意版本。图省事时用,但不可复现——今天装的和明天装的可能不是同一个版本。
numpy==2.5.2:必须正好是它。复现实验的标准写法,缺点是锁得太死,别的包要求不同版本时会冲突。
numpy>=2.0:不低于 2.0。
只要求「有某个新特性」时用,但它允许装到未来任何版本,哪天出了破坏性变更就会突然崩。
numpy~=2.5.2:2.5.x 里最新的,但不跨到 2.6。
这在「要补丁、不要破坏性变更」时最合适——兼顾了安全和更新。
实际操作里常见的组合是:
顶层依赖用 ~= 或 >= 写宽一点,然后用 pip freeze 生成一份锁死的清单给部署用。
一份给人看,一份给机器看。
三、装到哪去了:最容易错的一步
pip install 装到「当前这个 pip 所属的环境」。而 pip 是哪个环境的,又取决于你敲的是哪一个。
这就有了套娃。
三种写法的差别:pip install 包名 装到 PATH 上第一个 pip 的环境(可能不是你想的);
python -m pip install 包名 装到这个 python 的环境;激活环境后 pip install 装到被激活的环境。
推荐永远用 python -m pip。 它把「哪个 python」和「装包」绑死在一起,少一层歧义。
排查「装了却 import 不到」时,第一件事就是换成这个写法再试一次。
还有一个隐蔽的坑:
装完不重启解释器,某些情况下 import 不到。 Jupyter 里尤其明显——它启动时就把模块表加载好了,
装完包得重启内核。这不是装错了,是没刷新。
四、装不上怎么办:四种常见原因
一是网络。 国内直连 PyPI 慢,换镜像源:
pip install 包名 -i https://pypi.tuna.tsinghua.edu.cn/simple。
建议一次配好,以后不用再敲(pip config set global.index-url ...)。
二是没有现成的轮子(wheel)。 纯 Python 包好办,带 C 扩展的包需要编译,
Windows 上没装编译器就会失败。这时候看报错里有没有「building wheel」——有就说明在尝试编译。
三是版本不兼容。 报错里会写「requires Python >=3.10」或者「no matching distribution」。
这时候要么换包版本,要么换 Python 版本。
四是权限。 系统 Python 的 site-packages 可能要管理员权限。
这也是用虚拟环境的理由之一——自己的文件夹,不用任何权限。
五、最后:把这一章连起来
三节合起来是一条线: 装 Python(别装 32 位、记住 PATH)→ 建虚拟环境(隔离、可删可重建)→ 装包(用 python -m pip、 写 requirements.txt)。 这条线跟算法无关,但它决定了你能不能把书上的代码跑起来。 很多人卡在这里就放弃了,误以为自己「学不会机器学习」——其实只是 pip 装到了另一个 Python 里。 全书到这里结束。 回头看: 十七个算法的原理在第 2、3 章,判断好坏的方法在第 4 章,把它们跑起来的地基在第 5 章。 三样都齐了,剩下的就是拿真实数据反复练。
六、动手 Demo:数一数环境里有什么,再核对一份清单
这一段不需要联网。
它做两件事:列出当前环境已装的包(这里 91 个),再拿一份五行清单去逐条核对——谁满足、
谁版本不对、谁压根没装。
核对的逻辑就是 pip install -r 干的事,只是我们把它拆开、把每一步的结果打出来,好看清它在干什么。
from importlib import metadata
# 这个环境里已经装了什么
for d in metadata.distributions():
print(d.metadata["Name"], d.version)
# requirements.txt 里的四种写法,含义完全不同
# numpy 任意版本
# numpy==2.5.2 必须正好是它
# numpy>=2.0 不低于 2.0
# numpy~=2.5.2 2.5.x 里最新的
# 永远用这种写法装包:把「哪个 python」和「装包」绑死
# python -m pip install -r requirements.txt
实跑输出:
--------------------------------------------------------------------
装包:把「要哪几行」写清楚
--------------------------------------------------------------------
装包本身只有一条命令:`pip install 包名`。麻烦的从来不是敲命令,而是
**「装哪个版本」「装到哪去」「以后怎么复原」**这三件事。
【一】这个环境里现在有什么
包 版本
------------------------------------------------
anyio 4.15.1
av 18.1.0
bitarray 3.11.0
bitstring 4.4.0
certifi 2026.7.22
cffi 2.1.1
charset-normalizer 3.5.1
click 8.5.0
一共 **91** 个已安装的包。**装包之前先数一遍,装完再数一遍**
——数字变了,才说明真的装进去了。
【二】requirements.txt 怎么读
实际项目不会一句一句 `pip install`,而是把依赖写进一个文本文件,**一行一个约束**,
然后 `pip install -r requirements.txt` 一次装完。写法有几种,含义完全不同:
写法 含义 什么时候用
----------------------------------------------------------------------------
numpy 任意版本 不关心,能跑就行
numpy==2.5.2 必须正好是这个版本 复现别人的环境
numpy>=2.0 不低于 2.0 只要求有某个新特性
numpy~=2.5.2 2.5.x 里最新的(不改中间位) 要补丁不要破坏性变更
【三】拿这份清单去核对现有环境
包 已装版本 要求 结果
----------------------------------------------------
numpy 2.5.2 == 2.5.2 满足
pyyaml 6.0.3 >= 6.0 满足
matplotlib 3.11.1 >= 3.8 满足
pandas 未安装 >= 2.0 缺
torch 未安装 >= 2.0 缺
**五个要求里 3 个满足,剩下的要么没装、要么版本不对。**
`pip install -r requirements.txt` 干的就是这件事:逐条核对,不满足就去装。
【四】装到哪去了:这是最容易错的一步
`pip install` 装到「当前这个 pip 所属的环境」。而 `pip` 是哪个环境的,
又取决于你敲的是哪一个——**这就有了一层套娃。**
你敲的命令 装到哪
----------------------------------------------------------------------------------------
pip install 包名 PATH 上第一个 pip 所属的环境(可能不是你想的那个)
python -m pip install 包名 这个 python 所属的环境
(激活环境后)pip install 包名 被激活的那个环境
**推荐永远用 `python -m pip` 这种写法。**
它把「哪个 python」和「装包」绑死在一起,少一层歧义。
**这是排查「装了却 import 不到」时第一个要换的写法。**
「一共 91 个包」这个数本身没什么意义,但它的变化有意义。 装包前后各数一次,
数字变了才说明真装进去了——这比「没报错」可靠得多。
核对表那五行是这一节的落点。numpy 2.5.2 对上 ==2.5.2,满足;pyyaml 6.0.3 满足 >=6.0;
matplotlib 3.11.1 满足 >=3.8;pandas 和 torch 是「未安装」,直接判缺。
「五个里三个满足」这个结果很典型。真实项目里清单几十行,永远是「大部分满足、少数几个不对劲」。
关键是让工具去核,不要靠人记。
最后那段讲「装到哪」的三种写法,值得抄在便签上。
pip install 和 python -m pip install 看起来只差几个字符,装错地方的时候能查一整天。
30 秒实验
- 用
pip freeze导出一份清单,再和新环境对比,差多少行? - 把清单里的
>=全改成==并写上当前版本,这份清单在别的机器上能一次装成吗? - 故意写一个不存在的包名去核对,看报错长什么样——和「版本不满足」的报错有什么区别?
常见误区
- 用
pip而不是python -m pip。前者跟着 PATH 走,可能装到别的环境里。 后者把「哪个 python」和「装包」绑死。 - requirements.txt 全写
>=。今天能装,半年后某个包出了破坏性更新就崩。 给人看的写宽,给机器装的锁死。 - 装完不验证。「没报错」不等于「装上了」。
装完立刻
python -c "import 包名; print(包名.__version__)"。
自测三问(点开对答案)
1. `pip install` 和 `python -m pip install` 有什么区别? —— 前者用 PATH 上第一个 pip,装到它所属的环境; 后者用「这个 python」的 pip,装到这个 python 的环境。后者没有歧义,推荐使用。 2. `==`、`>=`、`~=` 三种写法分别适合什么场景? —— `==` 锁死版本,用于复现;`>=` 只要不低于某个版本,用于「需要某个新特性」; `~=` 允许补丁级更新但不跨次版本,用于「要修 bug 但怕破坏性变更」。 3. 装完包 import 不到,最先检查什么? —— 先确认装到了哪个环境:`python -c "import sys; print(sys.executable)"`, 再确认用的 pip 是不是同一个环境。Jupyter 里还要重启内核。全书完。 十七个算法、一套评估方法、一条环境搭建路线——接下来该做的是找一份自己真正关心的数据, 把这条流水线从头跑一遍。
- ☐ (全书完)