AI 技术博客
返回首页
Python 基础 18 分钟阅读

包管理 pip 实战:安装、卸载、锁定与国内镜像源

Pythonpip包管理镜像源依赖锁定

引言

第 4 篇我们解决了「每个项目一个干净的屋子」——虚拟环境。但屋子里要摆什么家具、家具从哪来、怎么保证下次买到的家具和这次一模一样?这是这一篇的主题:包管理。工具是 Python 官方包安装器 pip(Pip Installs Packages 的递归缩写,也是「优先用 pip」这句骂名——不过这并不妨碍它好用)。

读者应先掌握第 4 篇的全部内容:创建并激活虚拟环境、python -m pip 的调用方式、site-packages 的隔离原理。本文目标:能熟练完成「查找 → 安装 → 验证 → 卸载」的日常循环,能把依赖锁定成 requirements.txt 并在新机器上重放,能配置国内镜像源解决下载慢问题,能在无网络环境用离线包安装。全部命令都基于 pip 25 在本机实测验证(你的 pip 版本以 python -m pip --version 为准,命令一致)。

概念与原理

pip 从哪来、装的是什么

pip 从索引(index)下载包,默认索引是 PyPI(Python Package Index,Python 包索引,第 1 篇介绍过,托管 50 万+ 包)。pip 能安装两种分发格式:

  • wheel(.whl):打包好的「成品」,又分纯 Python 版(如 requests-2.34.2-py3-none-any.whl,任何平台通用)与带编译产物的平台版(如 charset_normalizer-3.5.1-cp312-cp312-win_amd64.whl,文件名里的 cp312 表示 CPython 3.12、win_amd64 表示 64 位 Windows)——这类 wheel 是预编译的,装完即可用,不需要本机编译器;
  • sdist(源码包,.tar.gz):源码形式,安装时若没有对应 wheel,pip 会现场构建——这要求本机有 C 编译器,也是「装某个包报编译错误」的根源(解决方案通常是用镜像源或换用有 wheel 的版本)。

pip 安装时自动解析依赖树:装 requests 会同时装 certifi、charset-normalizer、idna、urllib3 四个依赖并校验版本兼容性;依赖找不到兼容版本时给出明确的冲突报错。依赖冲突长什么样?本机实测(模拟安装两个互相排斥的版本组合):

ERROR: Cannot install idna==2.0 and requests==2.31.0 because these package versions
have conflicting dependencies.
ERROR: ResolutionImpossible: for help visit
https://pip.pypa.io/en/latest/topics/dependency-resolution/#dealing-with-dependency-conflicts

ResolutionImpossible 的意思是:在当前版本约束下,pip 无法找到一组彼此兼容的版本。解法不是绕开报错,而是放宽其中一个约束(本例 requests>=2.31.0 要求 idna>=2.5,<4,强行装 2.0 当然冲突)。看懂这类报错,是排查「装不上」问题的一半功力。

版本说明符:把「装哪个版本」讲清楚

pip 的版本说明符(version specifier)语法如下,都放在引号里传给命令:

写法含义示例
==精确锁定requests==2.31.0
>= / <=大于等于 / 小于等于requests>=2.28
~=兼容版本:允许同次版本内升级requests~=2.31.0 等价 >=2.31.0,==2.*
!=排除某版本requests!=2.30.0
*通配requests==2.31.*

组合用逗号:"requests>=2.28,<3.0"。安装时命令名与说明符之间不要留空格(requests ==2.31.0 是错误写法),完整版用引号包住 "requests==2.31.0",避免被 shell 的字符解释干扰。

为什么需要国内镜像源

pip 默认直连 PyPI(位于国外),国内网络环境下经常慢、超时、断流。镜像源(mirror)是 PyPI 的定时同步副本,放在国内服务器,访问快得多。几个真实可用的镜像(均长期维护,选一个即可,教程示例用清华 TUNA 镜像):

  • 清华 TUNA:https://pypi.tuna.tsinghua.edu.cn/simple
  • 阿里云:https://mirrors.aliyun.com/pypi/simple
  • 腾讯云:https://mirrors.cloud.tencent.com/pypi/simple

镜像内容与 PyPI 基本一致(同步有时差,新发布的包可能延迟数小时到一天),下载源改变不影响包的内容——包文件有哈希校验。同理,公司内网也会自建 PyPI 私有源(配合制品库工具如 devpi、Nexus),用法完全相同:把 URL 换成内网地址即可——所以「换源」这个技能一次学会,处处通用。

配置优先级:三处设置谁说了算

pip 的配置来源按优先级从高到低:命令行参数 → 环境变量(PIP_INDEX_URL 等 PIP_* 系列)→ 配置文件。配置文件的位置:Windows 在 %APPDATA%\pip\pip.ini,macOS/Linux 在 ~/.config/pip/pip.conf(或 ~/.pip/pip.conf)。这也解释了为什么「命令行加了 -i 有效、换台机器又变慢」——命令行参数只对本条命令生效,持久化要靠配置文件。

操作/实现

下面的操作请在已激活的虚拟环境中进行(第 4 篇的步骤),避免污染全局。为便于复现,先创建演示环境:

python -m venv .venv && source .venv/bin/activate   # Windows PowerShell: .venv\Scripts\activate

安装与版本指定

默认装最新版:

python -m pip install requests

本机实测:安装后 import requests 并打印版本:

requests 2.34.2 OK

指定精确版本(注意引号与 ==):

python -m pip install "requests==2.31.0"

实测安装后版本变为 2.31.0。而模拟安装(不真正落盘,用于验证「能不能装」)是:

python -m pip install --dry-run "requests==2.31.0"

输出关键行:

Would install requests-2.31.0

检查某个包所有可用版本(实验性命令,会打印实验性警告,版本以本机为准):

python -m pip index versions requests

查看与卸载

pip list 列出全部已装包,本机(隔离环境)实测:

Package            Version
------------------ ---------
certifi            2026.7.22
charset-normalizer 3.5.1
idna               3.19
pip                25.0.1
requests           2.34.2
urllib3            2.7.0

pip show <包名> 查看单个包的详细信息(版本、依赖、主页等):

python -m pip show requests

卸载(-y 跳过确认):

python -m pip uninstall -y requests

卸载后 import requests 立刻报 ModuleNotFoundError——这是验证「真的卸干净了」的标准信号。

锁定:requirements.txt 与 pip freeze

「锁定」指把当前环境的依赖及其精确版本记录下来,供以后重放。两条命令:

python -m pip freeze        # 输出所有包的 name==version 行
python -m pip freeze > requirements.txt   # 写入文件

本机实测 pip freeze 输出:

certifi==2026.7.22
charset-normalizer==3.5.1
idna==3.19
requests==2.34.2
urllib3==2.7.0

注意两点:freeze 出来的每一行都可用 pip install -r 原样输入(这就是「锁定 → 重放」闭环);它是「输出格式」,不是「手写清单格式」。在新环境一次性重放:

python -m pip install -r requirements.txt

本机实测:新建第二个虚拟环境执行上述命令后,pip list 与源环境完全一致(requests 2.34.2、pip 25.0.1 及其余依赖逐条对齐)。工程上的分工建议:requirements.txt 用 pip freeze 生成,做完全锁定(连传递依赖一起锁);若想只列顶层依赖、让 pip 自由解析,可另写 requirements.in 并结合 pip-tools 等工具——那是进阶话题,本篇先用好 freeze。另一个惯例:运行依赖与开发依赖分开,例如测试/构建工具写在 requirements-dev.txt 中(文件里可用 # 注释说明每个包的用途),两条清单各自锁定、分别重放,避免把开发工具装进生产环境。

依赖一致性体检:pip check

依赖锁定之后,环境里是否真的「两两兼容」?pip 提供了体检命令:

python -m pip check

在刚装好 requests 的干净环境里,本机实测输出:

No broken requirements found.

若某个包要求的版本与已装包冲突,它会列出具体的「broken」信息。建议在每次安装/升级后跑一次,几秒换来的是一层安心。

升级 pip 自身

pip 本身也是包,落后版本可能缺少新特性与依赖解析修复。升级它只需要:

python -m pip install --upgrade pip

在虚拟环境里执行时,升级的只是当前环境的 pip,不影响全局——又一次体现隔离的好处。建议每隔一段时间升级一次,版本号以 python -m pip --version 为准。

配置国内镜像源

一次性用法(仅本次命令):

python -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyyaml

本机实测:通过清华镜像安装 PyYAML 成功,pip show pyyaml 显示 Version: 6.0.3——镜像内容与官方一致。

持久化配置(推荐,装一次永久生效):

python -m pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

本机实测:命令把配置写入用户级配置文件(Windows 为 %APPDATA%\pip\pip.ini),内容如下:

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

之后所有 pip 命令默认走镜像。查看当前全部生效配置:

python -m pip config list

想恢复官方源,执行 python -m pip config unset global.index-url 即可。

离线安装:pip download + —no-index

内网/无网环境是真实场景,流程分两步:联网机器下载、离线机器安装。联网机器执行:

python -m pip download requests -d wheels

本机实测 wheels/ 目录内容:

certifi-2026.7.22-py3-none-any.whl
charset_normalizer-3.5.1-cp312-cp312-win_amd64.whl
idna-3.19-py3-none-any.whl
requests-2.34.2-py3-none-any.whl
urllib3-2.7.0-py3-none-any.whl

download 会把目标包连同依赖一起取出。把 wheels 目录拷到离线机器后:

python -m pip install --no-index --find-links wheels requests

--no-index 禁止访问任何索引,--find-links 指定本地目录。本机实测:全新虚拟环境中安装成功,requests.__version__ 输出 2.34.2。注意:平台特定 wheel(如上面的 charset_normalizer-...-win_amd64.whl)只适用于相同架构——下载时若知道目标平台不同,应加 --platform 或直接下载 sdist,这属于进阶话题。

本地缓存:pip cache

下载过的包不会重复下——pip 把 wheel 缓存到本地(本机实测缓存目录:c:\users\<用户名>\appdata\local\pip\cache)。三条常用命令:

python -m pip cache dir     # 缓存目录在哪
python -m pip cache list    # 缓存了哪些 wheel
python -m pip cache info    # 缓存占用统计

本机实测 pip cache info 的部分输出:

Package index page cache size: 110.5 MB

意义有二:一是重装/换环境时命中缓存会明显变快(对有网但慢的环境是安慰,对断网重装环境是救命);二是当你怀疑「缓存里的旧版本污染了新安装」时,python -m pip cache purge 清空重来——不过这极少必要,pip 的缓存按内容寻址、不会悄悄投毒。

易错点与陷阱

易错点 1:pip 装到了「错误的解释器」。 未激活环境(或 pip 与 python 分属不同解释器)时执行 pip install,包进了全局或另一个环境,随后 import 失败。对策就是第 4 篇练过的固定搭配:始终 python -m pip ...,且装前确认 which python 在 .venv 内。

易错点 2:把 pip freeze > requirements.txt 的产物再喂回 pip install -r,导致「requirements.txt 引用自己」的死锁。 正确的读写方向是:freeze 是输出(锁定现状),-r 是输入(重放)。常见翻车现场是项目里只放了一个自产自销的 requirements.txt,新人 pip install -r requirements.txt 装不上任何东西——请检查文件里是否只有 requirements.txt==... 这种行。

易错点 3:锁定了却用 pip install -U(或升级命令)悄悄破坏锁定。 -U 会把包升级到最新版本,如果随后发生兼容问题,而你手头的 requirements.txt 还是旧的,环境就与清单脱节了。规则:要动版本就改清单(或重新 freeze),要让环境与清单一致就用 -r。

易错点 4:镜像配置「这次有效、下次失效」。 命令行 -i 只对本条命令生效;新人常因此以为镜像没配好。持久化必须走 pip config set global.index-url ...(或环境变量 PIP_INDEX_URL),并用 pip config list 验证。

易错点 5:以为 pip list 等于 pip freeze。 两者列出相同的包集合,但格式与用途不同:list 是人类可读的表格(含 pip 自身),freeze 是机器可重放的 name==version 行(不含不可重放的条目)。写脚本、做重放请用 freeze。

小结

本文是 pip 的完整实战:它的来源与两种分发格式(wheel/sdist)、版本说明符语法(==、~=、>= 等)、依赖自动解析;安装/精确版本/模拟安装/查看/卸载的日常循环;用 pip freeze > requirements.txt 锁定、用 pip install -r 重放;清华、阿里、腾讯三个国内镜像源的一次性与持久化配置;以及 pip download + --no-index 的离线安装链路。五个易错点提醒:解释器对应关系、freeze 与 -r 的方向、-U 对锁定的破坏、镜像配置的持久化、list 与 freeze 的分工。至此,环境搭建与运行原理的「基建五件套」全部就位:语言选择、安装、原理、隔离、依赖。下一篇文章起,我们将走进交互式编程——让命令行成为你的第二大脑。

练习与思考题

  1. 在虚拟环境中执行 python -m pip freeze > requirements.txt,然后新建第二个虚拟环境,用 python -m pip install -r requirements.txt 重放,对比两个环境的 pip list。(答案导向:包名与版本逐条一致。)
  2. 用 python -m pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple 配置镜像,再用 python -m pip config list 验证;回答配置文件在 Windows 与 macOS/Linux 上的路径。(答案导向:Windows %APPDATA%\pip\pip.ini;macOS/Linux ~/.config/pip/pip.conf。)
  3. 写出 requests~=2.31.0 与 requests==2.31.* 展开后的等价比较式,说明它们的区别在哪。(答案导向:前者是 >=2.31.0,==2.*,允许 2.x 内所有大于等于 2.31.0 的版本;后者只允许 2.31.x 补丁版本。)
  4. 思考题:为什么 pip freeze 会同时锁住 certifi、urllib3 等「你从没直接装过」的包?(答案导向:它们是 requests 的传递依赖,间接引入;锁定它们才能保证重放环境的字节级一致——这正是「可复现构建」的基础。)