Anaconda 把 Python 本体加几百个科学计算包打成一个安装包,装一次全都有。 代价是体积大、版本被它统一管着;好处是新手不用逐个排查依赖冲突。 本机环境装了 135 个分发包;pandas 声明 82 条依赖,其中只有 5 条是真的运行时要的。
上一篇的 PyCharm 是编辑器,这一篇的 Anaconda 是「一整套环境」。两者不冲突,可以同时装。 安装界面本沙箱不执行;但「装了多少包」「依赖长什么样」这两件事,可以现场数出来。
一、它解决的到底是什么问题
pip 装一个包,会连带装它的依赖。装十个包,依赖可能有几十个,还互相约束。 约束一冲突,pip 就麻烦了:新版直接报错退出,老版静默装一个、另一个跑起来才炸。 Anaconda 的做法是:把常用的一套包按一组互相兼容的版本打包,一次装好。
它替你做了取舍。代价是你拿到的常常不是最新版,而是「它算过能共存」的那一版。
二、装完大概是什么样
体积几个 GB,装完自带 Anaconda Navigator(图形界面)和 conda 命令(命令行)。 预装的有 numpy、pandas、matplotlib、scipy、scikit-learn、jupyter 这一套。 本机虽然不是 Anaconda,但装了同类的一批包,当前环境一共 135 个分发包。
135 这个数说明一件事:你以为只装了几个,其实每个都拖了一串。
三、依赖长什么样
拿 pandas 举例,它的元数据里声明了 82 条依赖。 但其中只有 5 条是真的运行时依赖:numpy、python-dateutil、tzdata 等。 剩下 77 条是「可选功能」——装 pyarrow 才支持的箭头格式、装 pytest 才跑的测试,这些都标了 extra。
还有一类是「按环境分支」:两条 numpy 一条给 3.14 以前,一条给 3.14 及以后。 同一条声明,在不同机器上生效的不是同一条。这就是为什么两台机器装出来可能不一样。
四、版本冲突是怎么发生的
假设 A 包要求 numpy < 2.0,B 包要求 numpy >= 2.0。两个都装,只能满足一个。 conda 的解法是先算全体约束,找一组都满足的版本。这个计算叫依赖求解。 pip 从 20.3 起也有求解器,但它的策略更偏「尽量装最新」,遇到死结会直接报错。
报错其实是好事:总比装完了跑起来才炸强。看到冲突报告,先读它说的那两条约束。
五、什么时候用 conda,什么时候用 pip
刚入门、要一次装齐:conda(或直接 Anaconda)。 要精确控制版本、要交付:venv 加 pip,配一个 requirements.txt。 要用 GPU 相关的库:conda 更省事,它提供预编译好的二进制。
两者不冲突,可以在 conda 环境里继续用 pip。 风险是 conda 不知道 pip 装了什么,下次 conda 更新可能把 pip 装的覆盖掉。
六、动手 Demo:Anaconda 那种打包方式,本质是什么
先数这台机器装了多少分发包,再拆开 pandas 的依赖声明,看里面有几条是真的。 最后把可选依赖和运行时依赖分开数一遍。
import importlib.metadata as md
names = {}
for d in md.distributions():
try:
n = d.metadata["Name"]
except Exception:
continue
if n:
names[n] = d.version
print("分发包 %d 个" % len(names))
reqs = md.requires("pandas") or []
hard = [r for r in reqs if "extra ==" not in r]
print("pandas 声明 %d 条依赖,其中运行时 %d 条" % (len(reqs), len(hard)))
for r in hard:
print(" %s" % r)
实跑输出:
--------------------------------------------------------------------
Anaconda 那种打包方式,本质是什么
--------------------------------------------------------------------
① 一次装齐,代价是什么
--------------------------------------------------------------------
Anaconda 把 Python 本体加几百个科学计算包打成一个安装包,装一次全都有。
代价有两个:体积大(几个 GB),以及版本被它统一管着——它说用哪个 numpy,你就用哪个。
好处也很实在:新手不用一个个 pip install,也不会遇到依赖冲突。
! 所以它适合「先跑起来再说」的场景,不适合「要精确控制版本」的场景。
② 现场数一遍:这台机器装了多少包
--------------------------------------------------------------------
当前环境装了 135 个分发包。
| 包 | 版本 |
|---|---|
| anyio | 4.15.1 |
| asttokens | 3.0.2 |
| attrs | 26.1.0 |
| av | 18.1.0 |
| bitarray | 3.11.0 |
| bitstring | 4.4.0 |
| blinker | 1.9.0 |
| certifi | 2026.7.22 |
| cffi | 2.1.1 |
| charset-normalizer | 3.5.1 |
| click | 8.5.0 |
| cloudpickle | 3.1.2 |
后面还有 123 个,最长的名字是 jsonschema-specifications。
! 包多不等于环境好。装得越多,两个包抢同一个依赖的概率越高。
③ 依赖是棵树,不是一张表
--------------------------------------------------------------------
pandas 声明了 82 条依赖,其中 5 条是真的运行时依赖,另外 77 条是可选功能(extras)。
numpy>=2.0.2; python_version < "3.14"
numpy>=2.3.3; python_version >= "3.14"
python-dateutil>=2.9.0
tzdata; sys_platform == "win32"
tzdata; sys_platform == "emscripten"
看那两条 numpy:一条给 3.14 以前,一条给 3.14 及以后。同一个包,按环境选不同版本。
这还只是第一层。每个依赖自己还有依赖,整棵树可能有几十个节点。
! pip install 一个包,实际装进来的是整棵子树。这就是为什么「我只装了一个包」之后环境变了几十个。
④ 版本冲突长什么样
--------------------------------------------------------------------
假设 A 包要求 numpy < 2.0,B 包要求 numpy >= 2.0。两个都装,pip 只能满足一个。
新版 pip 会直接报错退出,老版会静默装一个、另一个跑起来才炸。
Anaconda 的做法是:它先算一遍全体的约束,找一组都满足的版本,装给你。
! 这叫「依赖求解」。它不是更聪明,是替你做了取舍——所以它给的版本常常不是最新的。
⑤ 什么时候用 conda,什么时候用 pip
--------------------------------------------------------------------
| 情况 | 更合适 | 原因 |
|---|---|---|
| 刚入门,要一次装齐 | Anaconda | 省掉逐个排查依赖的时间 |
| 要精确控制版本 | venv + pip | 环境干净,装什么有什么 |
| 要用 GPU 相关的库 | conda | 预编译好的二进制,省去自己编 |
| 要交付给别人 | venv + requirements.txt | 体积小,能复现 |
! 两者不冲突,可以在 conda 环境里继续用 pip。混用的风险是 conda 不知道 pip 装了什么。
importlib.metadata 是标准库自带的,不用装就能读任何包的元数据。
extra == 这个过滤条件是关键:带它的都是「可选功能」,不是运行时必需。
不筛掉就会把 82 条当成 82 个硬依赖,结论完全错。
30 秒实验
- 随便挑三个包,看它们的依赖条数,哪个最多?
- 把过滤条件改成筛出 extras,数一数 pandas 有多少条可选依赖。
- 想一想:为什么「装完能用」和「装完版本最新」这两个目标会冲突?
常见误区
- 以为 Anaconda 里什么都有:冷门包照样要 pip 装。
- conda 和 pip 混着用不管顺序:conda 不知道 pip 装了什么,更新时会覆盖。
- 看到依赖冲突就硬装:
--force-reinstall能装上,但跑起来可能算错。 - 把 extras 当成必需依赖:那 77 条可选依赖,一条都不用装也能用 pandas。
自测三问(点开对答案)
1. Anaconda 相比 pip 逐个装,多做了哪件事? —— 它先算一遍所有包的版本约束,找一组互相兼容的版本一起装,而不是各装各的最新版。 2. pandas 那 82 条依赖里,为什么只有 5 条是运行时必需的? —— 其余 77 条标了 extra,只有装了对应可选功能(比如 pyarrow、pytest)才需要。 3. 为什么同一条依赖声明在两台机器上可能生效的不是同一条? —— 因为很多声明带环境标记,比如 python_version < 3.14,会按当前环境挑一条。环境装好了,下一个问题是「在哪儿写」。 数据分析最常见的写法是 Notebook——下一篇拆开它的文件结构,看它到底存了什么。
- ☐ (本篇完,下一篇 2.6 Jupyter Notebook:代码和笔记同在一页)