包管理基础:安装、更新、卸载,查看已安装的包列表

说起包管理,这其实是每次做环境时最基础的活儿。但在 Conda 生态里,基础不等于简单。很多人在入门时就养成了坏习惯——今天 pip 装一个,明天 conda 装一个,最后环境乱成一锅粥。

我自己早年间就吃过这个亏。有一次项目赶进度,随便往 base 环境里塞包,结果某个依赖版本冲突,整整排查了一天。从那以后,我对包管理的每个动作都格外注意。

说白了,包管理就是三件事:装什么、怎么升级、怎么清理干净。我们一个一个来看。

安装包:pip vs conda

安装一个包,最直接的方式就是:

conda install 包名

或者:

pip install 包名

但这两者背后的逻辑完全不同。Conda 是环境级的包管理器,它不光管 Python 包,还能管 C 库、动态链接库这些东西。而 pip 只管 Python 包,它不关心系统的二进制依赖。

举个例子,你想装一个做图像处理的 opencv。用 pip 装:

pip install opencv-python

这条命令只拉了一个 Python wheel 包。但如果你的系统缺少 opencv 所需要的底层库(比如 ffmpeg),那可能运行时就报错。

用 conda 装:

conda install opencv

Conda 会自动把背后的 libopencv、ffmpeg 等 C 库一起装好。这就是我为什么建议优先用 conda——省心,尤其在内网环境或服务器上。

我的习惯:能用 conda 装的包,尽量用 conda。只有 conda 源里没有的时候,才用 pip。混用的时候,先装 conda 包,后装 pip 包。顺序反了容易出问题。

安装指定版本

在实际项目中,很多时候不能装最新版,得锁定某个特定版本。比如:

conda install numpy=1.21.0

或者用 pip:

pip install numpy==1.21.0

我曾经在一个生产环境里,因为装了最新的 pandas 2.0,结果好几个旧脚本报错。那会儿我就明白了——版本锁定不是保守,而是负责。后面讲版本锁定策略时,我们还会深入聊这个。

包更新:要不要升级?

更新包听起来简单,但在项目里要慎重。命令就两行:

conda update 包名
conda update --all

或者:

pip install --upgrade 包名

你想想看,更新一个包,可能带来依赖链上的连锁反应。我记得有一次,我随手更新了 requests 库,结果把整个环境的 urllib3 版本都带偏了,导致另一个核心模块没法正常发送 HTTP 请求。

所以我的原则是:非必要不全局更新。真要更新,先读 release notes,再看依赖变化。最好在隔离的环境里测试完再推广。

请注意:conda update --all 可能会把 Anaconda 自身的核心包也升级,有时反而导致环境不稳定。在正式项目里,我基本不用这个命令。

卸载包:清理要彻底

安装容易,卸载也不难:

conda remove 包名

或者:

pip uninstall 包名

但这里有一个坑——依赖不会自动跟随删除。什么意思呢?你装 A 包时,自动装上了它的依赖 B。等你卸载 A 包,B 包仍然留在环境里。久而久之,环境里就会有一堆「孤儿包」。

我踩过一个坑:在一个长期维护的项目里,积攒了很多无用的遗留包,最终导致 conda solve 解析依赖时越来越慢,甚至出现莫名其妙的不一致。后来我专门写了个脚本,定期清理没有反向依赖的包。

建议做法:卸载一个包后,顺手检查一下它引入了哪些额外依赖。可以用 conda list --revisions 查看环境变更记录,反向追踪哪些包可以一并清理。

查看已安装的包列表

查看当前环境里的包,应该是每天都要做的操作:

conda list

这条命令会输出一个表格,包含包名、版本、来源渠道。输出格式是这样的:

# packages in environment at /opt/conda/envs/my_project:
#
# Name                    Version                   Build  Channel
numpy                     1.21.0           py39h20f2e39_0    conda-forge
pandas                    1.3.0            py39h1d20d9e_0    conda-forge
python                    3.9.6                h12debd9_0    defaults
...

如果你用的是 pip,查看命令是:

pip list

或者想看更详细的信息:

pip show 包名

我个人习惯是用 conda list 作为主要查看工具,因为它能同时显示从 conda 和 pip 安装的包(前提是你在 conda 环境内)。不过要留意,单纯用 conda list 看到的 pip 包信息可能不全,必要时还是得用 pip list 补一下。

对比一下:
功能Conda 命令Pip 命令
安装conda installpip install
指定版本安装conda install 包名=版本pip install 包名==版本
更新conda updatepip install --upgrade
卸载conda removepip uninstall
查看列表conda listpip list

环境快照:export 与 list 的巧妙运用

查看包列表,不只是为了看一眼。更重要的是记录当前环境的精确状态。这在后面做版本锁定时至关重要。

把你当前环境的包列表导出成文件:

conda list --export > requirements.txt

或者更精确的方式——只记录你显式安装的包,不记录自动依赖:

conda list --explicit > spec-file.txt

这个 spec-file.txt 就是环境快照。你可以用它重建一个一模一样的环境:

conda create --name new_env --file spec-file.txt

嗯,这里要注意:--explicit 生成的 URL 中包含 build 信息和渠道,跨平台可能会失效。如果你的团队需要在多个操作系统上复现环境,建议用 conda env export 导出 yml 格式。

conda env export > environment.yml

这种 yml 文件是跨平台的,后续直接拿来创建环境就好。

提醒一下:千万别直接拿 conda list 的终端输出截图当记录。那东西没法回放。一定要保留 --export 或 env export 生成的可重入文件,才能确保环境能一键复现。

知识结构图:包管理操作全流程

下面这张图总结了本章的核心逻辑,从依赖解析到最终环境激活,每一步都和前后的审计与版本锁定策略有关。

包管理生命周期流程图 安装包 依赖解析 (Conda solver) 安装成功 查看列表 更新包 卸载包 环境快照 (--export / env export) 版本锁定策略 (spec-file / yml) 说明:橙色节点是日常操作,紫色节点是核心审计链路,绿色/红色表示操作结果状态

日常操作 checklist

为了不遗漏关键步骤,我整理了一个简洁的 checklist。做环境管理时,按照这个顺序过一遍就好:

  1. 安装新包前:先确认环境中是否存在,避免重复安装。
  2. 指定版本:用 == 或 = 精确锁定版本。
  3. 更新时:不要用 --all,改为逐个更新并检查依赖。
  4. 卸载后:检查是否有遗留依赖,可以考虑 conda clean --packages 清理缓存。
  5. 导出快照:每次重大变更后,运行 conda env export > snapshot.yml。
  6. 审计:定期用 conda list --revisions 回溯变更记录。

这些看起来都是基础操作,但越基础的东西,越容易在日常中出错。我在项目里见过太多因为「装一个包没指定版本」导致环境不可复现的案例。

所以,从这一章开始,我希望你能养成习惯:每次安装或更新包,都把它当作一次审计动作来做。记录、对比、锁定——这是后面所有容器化和审计工作的基石。这一套基础打牢了,后续讲版本锁定策略时会顺很多。