ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

pkg_resources缺失?从setuptools修复到Python打包链路解析

pkg_resources缺失?从setuptools修复到Python打包链路解析 1. 一条报错背后的连锁故障setuptools是怎么悄悄“消失”的先还原一个场景。某天你在终端里执行pip install想装一个包解决燃眉之急结果蹦出来的不是进度条而是一行刺眼的ModuleNotFoundError: No module named pkg_resources。这时候绝大多数人的第一反应是去pip install pkg_resources然后发现pip自己也跑不起来了或者装了半天提示“Requirement already satisfied”但报错依旧存在。问题到底出在哪先说结论pkg_resources不是独立分发的第三方库它是setuptools这个库底层的核心模块。Python 生态里有一整套由pip、setuptools、wheel协同驱动的打包和安装机制而pkg_resources是setuptools提供的、用于在运行时解析包版本和依赖关系的关键组件。报错说找不到pkg_resources基本可以断定是setuptools被破坏、被卸载或者当前 Python 环境里根本没有安装它。这个故障比想象中更常见而且触发原因五花八门。比如你把系统自带的 Python 从 3.8 升到 3.10之前装在旧版本里的setuptools并不会跟着迁移再比如你在虚拟环境里手滑执行了pip uninstall setuptools或者在某个项目里强制指定了--no-build-isolation导致构建隔离环境里缺了setuptools。另一个高频场景是使用pyenv、conda、uv这类 Python 版本管理工具时切换解释器后路径变了而环境变量还指向旧的 site-packages。这个报错真正的危险之处在于它不是“装不上某个包”这么简单而意味着整个 Python 环境的依赖解析链路断了一环。因为pip在安装很多带构建脚本的包时会调用setuptools里的pkg_resources去读取包元数据你在代码里只要写了import pkg_resources比如用pkg_resources.get_distribution(xxx).version获取版本号也会直接触发这个报错。所以无论你是用pip装包还是跑某个依赖了pkg_resources的脚本都会翻车。通常这篇内容会直接甩给你一串命令但我更想做的是先把问题的根因链路讲清楚。因为如果你不理解为什么pip install setuptools有时能解决问题、有时不行下次踩坑你还是会懵。后面我会用一次真实环境的排查过程来展示完整思路再给出修复方案和避坑经验。2. 排查链路从“ModuleNotFoundError”到定位setuptools损坏既然标题里写着“你的setuptools可能出大问题”那我们就要用排查问题的方式一步步逼近真相。很多人在网上搜到这个报错照着帖子敲命令结果发现自己的情况跟帖子里不完全一样原因就在于他们没有先确认自己的环境状态。下面是我建议的排查顺序每条命令背后都有它的逻辑。2.1 先确认解释器路径别被“虚拟环境”骗了报错信息里最容易被忽略的信息是“当前用的到底是哪个 Python”。很多人开着 IDE 或终端默认以为用的是某个虚拟环境但实际上加载的可能是系统 Python或者是pyenv管理下的另一个版本。which python which pip python -c import sys; print(sys.executable)我自己排查这种问题时第一条命令永远是python -c import sys; print(sys.executable)确认出来的路径是否和我预期一致。如果发现终端里python指向/usr/bin/python3但你明明启动的是虚拟环境说明虚拟环境没有被正确激活后续所有修复动作都会作用错地方。还有一种情况which python和which pip指向两个完全不同的目录。比如python是/usr/local/bin/python3.9而pip是/usr/bin/pip3这是因为 pip 脚本的 shebang 里写死了某个解释器路径或者系统里有多个 Python 共存时 PATH 顺序错乱。这种情况下你执行pip install其实是给另一个 Python 装包当然解决不了当前解释器的pkg_resources缺失。2.2 检查sys.path看解释器实际加载了哪些目录确认了解释器路径后下一步是看sys.path里到底有哪些搜索目录。python -m site这个命令会列出当前解释器的 site-packages 路径。如果输出里显示path/lib/python3.10/site-packages这个路径不存在于磁盘上说明解释器配置有误或者你正在用一套“半迁移”的环境。更直接的方式是python -c import sys; print(\n.join(sys.path))对比这些路径是否存在、权限是否可读。如果路径里出现了多个版本的 Python 目录混在一起那基本可以确定是环境变量 PYTHONPATH 或.pth文件搞的鬼。2.3 问 pip 要自己的状态pip --version和pip debug会告诉你更多在pkg_resources缺失的情况下pip的自身功能往往已经受损但它的报错方式很多样pip --version正常情况会输出类似pip 23.2.1 from /usr/local/lib/python3.10/site-packages/pip (python 3.10)。如果pip命令直接报ModuleNotFoundError: No module named pkg_resources那说明 pip 在启动阶段就已经加载失败。有人问为什么 pip 自己也要用pkg_resources因为pip在运行时需要解析已安装包的元数据而这些元数据的读取机制在很早之前就是基于pkg_resources的。pip21.3 之后逐步迁移到importlib.metadata但仍有大量依赖链没有完全摆脱pkg_resources。所以当setuptools整个缺失时pip 也会处于半瘫痪状态。2.4 检查现有 setuptools 的“尸体”如果你用pip show setuptools会报错用python -c import setuptools; print(setuptools.__version__)也报ModuleNotFoundError而setuptools的目录还在 site-packages 里这就是典型的“包文件损坏”或“元数据不完整”。常见原因包括强制中断了pip install setuptools的写入过程导致目录不完整手动删除了 site-packages 里的某个文件破坏了目录结构多个工具比如 conda 和 pip混用时互相覆盖了文件磁盘空间不足写入了一半就失败了。2.5 用一条命令全面掌握环境状态综合上述步骤我习惯用一条命令快速摸底python -c import sys; print(sys.executable); print(sys.version); print(sys.path) python -m pip --version如果这条命令里pip已经报ModuleNotFoundError那就跳过后续任何pip install操作直接进入修复环节。记住在环境破损状态下任何依赖pip执行的操作都不可靠你需要的是一套能绕过 pip 的修复路径。3. 修复方案的三板斧从最稳到最激进修复pkg_resources缺失本质上就是恢复setuptools。但恢复方式有讲究不同场景下适用的手段也不同。下面我按“稳妥程度”从高到低排列你先判断自己的环境状况再选。3.1 方案A用 ensurepip 走官方内置机制ensurepip是 Python 官方内置的一个工具模块专门用于引导安装或修复pip和setuptools。在 Python 3.12 之前ensurepip默认会同时安装setuptools和pipPython 3.12 之后ensurepip默认不再捆绑setuptools只装pip这一点后面单独说。python -m ensurepip --upgrade这条命令会自动将pip和setuptools重新安装到当前解释器的 site-packages 中。如果之前setuptools整个丢了这招十有八九能救回来。执行完后再用python -c import pkg_resources; print(ok)验证。如果输出ok说明链路已恢复。我为什么把它排在第一方案因为ensurepip用的是 Python 安装包自带的、校验过的安装源不依赖网络不依赖 pip 自身也不依赖 PyPI 的可用性。在断网、内网、代理有问题等恶劣环境下这个方案依然能工作。3.2 方案B用 get-pip.py 脚本重新部署如果ensurepip因为某些原因失败了比如 Python 是由源码编译安装但没有把 ensurepip 组件编进去或者是 Python 3.12 环境需要同时恢复 setuptools更通用的做法是用get-pip.pycurl -fsSL https://bootstrap.pypa.io/get-pip.py -o get-pip.py python get-pip.py这个脚本会自动安装pip、wheel、setuptools兼容性非常好。它的逻辑是先下载对应版本的 wheel 包再解压写入 site-packages。由于它只依赖标准库即使当前环境里 pip 已经瘫痪它也能正常执行。需要注意get-pip.py需要联网访问bootstrap.pypa.io如果你的机器在隔离网络里需要先手动下载脚本再在目标机器上执行。还有老生常谈的问题不要用sudo python get-pip.py除非你真的需要给全局环境装包。给你当前用户权限下可写的虚拟环境或用户目录安装就够了。3.3 方案C手动下载 setuptools wheel 直接解压方案 A 和 B 都要求 Python 解释器还能正常启动只是 import 某些模块失败。如果你的解释器本身也出现异常比如导入_ctypes失败连python -m ensurepip都跑不了那就得采用“降维打击”的方式手动下载 wheel 文件解压到 site-packages。先确认当前 Python 版本和平台python --version uname -m # Linux/Mac python -c import platform; print(platform.platform())然后到 PyPI 上找到对应版本的setuptoolswheel 包比如setuptools-68.0.0-py3-none-any.whl。因为 setuptools 是纯 Python 实现基本上py3-none-any的 wheel 在任何平台上都能用不用特意区分操作系统只要能跑 Python 3 就行。下载完成后用 Python 标准库直接解压python -c import zipfile; zipfile.ZipFile(setuptools-68.0.0-py3-none-any.whl).extractall(/path/to/site-packages)或者你用unzip命令也行只要解压到 site-packages 根目录即可。我一般不建议普通用户走这一步因为手动解压会导致 site-packages 里出现散落的.py文件而不是规范的.dist-info目录管理形式后续pip在解析包元数据时可能会漏掉它甚至引发包冲突。这个方法只作为“紧急救援”来用。3.4 修复完成后必须做的一步验证不管用哪种方案修完之后别急着跑业务代码先做三层验证# 1. 确认模块可导入 python -c import pkg_resources; print(pkg_resources.__file__) # 2. 确认版本信息 python -m pip --version python -c import setuptools; print(setuptools.__version__) # 3. 实际安装一个小包测试 python -m pip install --upgrade pip第三层是为了验证 pip 的完整链路是否恢复。如果这条命令能顺利跑完说明不仅是pkg_resources回来了pip 调用 setuptools 构建 wheel 的整个管道也通了。3.5 修复方案的对比与适用场景为了方便你直接对照我把三种修复方案的适用场景整理成一张表修复方案适用场景依赖前提恢复内容风险等级python -m ensurepip --upgradesetuptools 缺失或损坏Python 3.11 及以下解释器正常启动ensurepip 组件存在pip、setuptools低get-pip.pyensurepip 不可用、Python 3.12 需要恢复 setuptools、pip 完全瘫痪解释器能启动可访问 bootstrap.pypa.iopip、wheel、setuptools低手动解压 wheel解释器模块加载异常以上方案均失败能定位 site-packages 路径能下载 wheelsetuptools中提示如果你同时装了 conda 和 pip修复 setuptools 时一定要注意作用对象。conda install setuptools只会修 conda 环境里的那个实例python -m pip同理。很多“修了还是不行”的案例其实是两套工具链指向了不同的 site-packages。4. 别急着装回setuptools先解决掉环境里的“幽灵依赖”把setuptools恢复之后还有一个更隐蔽的问题等着你那些原本依赖pkg_resources的已安装包它们的“依赖登记”还残留在旧有的元数据里而实际文件可能已经被破坏了。这种状态我称为“幽灵依赖”——包管理器的记录还在但文件已经不在或已损坏。你继续装新包的时候pip 会在安装过程中逐一检查这些元数据一旦发现对不上的地方各种奇奇怪怪的报错又会冒出来。4.1 怎么判断环境里有多少“幽灵依赖”先跑一下python -m pip check这个命令的作用是检查所有已安装包的依赖是否满足。如果输出No broken requirements found.说明依赖关系完整如果列出一串pkg_resources 0.0.0 is not installed说明有一批包在元数据里记录了需要 pkg_resources但包管理器的索引里找不到它。另一种更直接的检查方式python -c import pkg_resources; print([d.project_name for d in pkg_resources.working_set])这条命令会列出pkg_resources当前能看到的、持有有效元数据的所有已安装包。如果输出和你实际安装的包对比少了一大截说明那些少的包元数据已经不完整了。4.2 逐个修复还是推倒重建这取决于“幽灵依赖”的数量。如果只有一两个包有问题可以直接卸载重装python -m pip install --force-reinstall --no-deps 包名注意我加了--no-deps因为重新安装这个包时如果按默认方式去解析依赖可能又触发其他包的问题所以先把它单独装好不去动依赖树。如果问题包超过五个或者你根本想不起来这个环境里曾经装过什么那我强烈建议直接新建虚拟环境从零开始重新安装项目依赖。理由很简单Python 包管理的一个显著特点是“环境状态难以完全可视化”你永远不知道哪些包之间发生了什么隐式交互与其花半天时间去补洞不如把整个地基重新打一遍。python -m venv /path/to/venv source /path/to/venv/bin/activate python -m pip install --upgrade pip setuptools wheel python -m pip install -r requirements.txt这套流程看着平平无奇但它能保证所有包都在同一套元数据解析逻辑下重新安装。特别是setuptools版本会变成最新版修复掉旧版本里已知的问题。4.3 升级 Python 版本后的“残留陷阱”这里单独提醒一个场景如果你是从 Python 3.8 升级到 3.10或者从 3.10 升级到 3.11系统里会残留旧版本 Python 的 site-packages 目录。而新解释器启动时可能因为.pth文件或 PYTHONPATH 的干扰把这些旧目录也加载进来于是出现一种很诡异的情况明明新环境里没有 pkg_resources但 import 却成功加载了旧环境的或者根本无法找到。我的建议是升级 Python 后不要试图保留旧环境的包直接创建新虚拟环境重新安装项目依赖。Python 的 ABI应用二进制接口在小版本升级时可能兼容但大版本升级时很多 C 扩展需要重新编译旧包强行留在环境里只会带来更多不稳定因素。4.4 “幽灵依赖”修复后的质量检查将这些“幽灵依赖”修复或环境重建完成后建议跑一遍下面的“三连检”# 1. 元数据一致性检查 python -m pip check # 2. 包列表与预期是否一致 python -m pip list # 3. 实际导入一个项目里的核心依赖确认调通 python -c import requests; print(requests.__version__)看起来很简单但很多人在第一步就翻了车pip check报了一堆依赖缺失而他们以为只要pkg_resources能导入就万事大吉了。记住pkg_resources的恢复只是第一步环境里那些“记录在案”的依赖关系才决定后续所有安装操作的稳定性。5. 为什么pip install装了“新”的setuptools问题依旧存在我在上面反复强调“环境破损状态下不要依赖 pip 操作”但实际中很多人已经执行过pip install setuptools还发现不起作用。这背后有几个很典型的原因值得单独拿出来讲透。5.1 原因一装到了另一个 site-packages最常见的坑你当前的 Python 解释器是/usr/bin/python3但pip命令来自/usr/local/bin/pip3。执行pip install setuptools时默认装到了/usr/local/lib/python3.x/site-packages而你的解释器在/usr/lib/python3/dist-packages里找包。两边各玩各的。排查方法很简单python -c import site; print(site.getsitepackages()) python -m pip show setuptools | grep Location对比两个路径是否一致。不一致的话以后的安装操作一律用python -m pip install 包名而不是pip install 包名确保 pip 始终和解释器绑定。5.2 原因二setuptools 装上了但版本太老或太新有些系统预装的 Python 里带的是很老的 setuptools比如 40.x而这些老版本在 Python 3.10 的环境里会有一部分代码触发 deprecation 警告甚至报错。反过来太新的 setuptools比如 70.x在某些老项目里会引入不兼容的元数据格式导致解析异常。我的做法是给setuptools指定一个稳定版本python -m pip install setuptools65.0,70.0这个范围在目前的主流项目中兼容性比较均衡。当然具体选哪个版本最好参考你的项目里是否锁定了 setuptools 版本比如requirements.txt或pyproject.toml里可能已经有约束。5.3 原因三site-packages 目录里存在“半损坏”的setuptools残留目录如果你曾经手动复制、强制中断安装过导致 site-packages 里出现了setuptools/目录但没有对应的.dist-info目录或者.dist-info里的RECORD文件不完整那么pip会认为 setuptools 已安装并跳过安装但实际导入时却报错。处理方法# 查看 site-packages 路径 python -c import site; print(site.getsitepackages()) # 找到 setuptools 相关目录 ls /path/to/site-packages | grep -i setuptools ls /path/to/site-packages | grep -i pkg_resources # 确认没有需要保留的修改后手动删除残留目录 rm -rf /path/to/site-packages/setuptools rm -rf /path/to/site-packages/setuptools-*.dist-info rm -rf /path/to/site-packages/pkg_resources删除后走一遍get-pip.py或者ensurepip重新安装。这个方法虽然粗暴但在遇到“幽灵目录”时比任何 pip 命令都有效。5.4 原因四conda 和 pip 的混用这个问题在数据科学相关环境里特别常见conda 维护一套 site-packagespip 也维护一套。安装时 conda 会把包放到 conda 的 site-packages而 pip 会把包放到另一个位置两者看起来都在envs目录下但细看路径完全不同。conda list setuptools python -m pip list | grep setuptools如果两个命令输出的版本不一致说明这套环境已经被“撕裂”了。解决思路是确定主线管理工具如果你以 conda 为主就统一用conda install安装一切包不行再考虑pip如果你以 pip 为主就别用 conda 去额外装包避免两套 toolchain 各自维护各自的元数据。提示在 conda 环境里执行pip install setuptools虽然通常可用但安装的版本不受 conda 的依赖解析管理。也就是说之后一旦运行conda install XXXconda 可能把 pip 刚装的 setuptools 当作“冲突项”导致环境状态再次被改写。5.5 如果你的报错里还有pkg_resources.DistributionNotFound如果你修复了pkg_resources的导入问题但代码里又出现pkg_resources.DistributionNotFound这说明pkg_resources本身已经能用了但它从元数据索引里找不到某个包。这通常是包没有正确安装、或者是这个包是在另一个 Python 环境里安装的。python -c import pkg_resources; pkg_resources.get_distribution(包名).version跑到这一步报错的话应当重新安装那个包。必要时检查是否把包安装到了当前虚拟环境之外。6. 从pkg_resources迁移到importlib.metadata给代码做一次“提前排雷”看到这里的读者可能已经解决了眼前的问题但我想再往前推一步。pkg_resources在 Python 生态里属于“日落”中的组件官方在setuptools的文档中已经明确表态不会移除但也不会再积极演进推荐新代码使用标准库的importlib.metadata和importlib.resources来替代。尽早把项目里对pkg_resources的依赖去掉能让你少踩很多坑。6.1 常见用法替换对照pkg_resources最常见的用法是获取包的版本号和资源文件路径。现在用标准库可以这样做# 旧写法获取包版本 import pkg_resources version pkg_resources.get_distribution(requests).version # 新写法使用 importlib.metadata from importlib.metadata import version ver version(requests)# 旧写法读取包内的数据文件 data pkg_resources.resource_string(my_pkg, data.txt) # 新写法使用 importlib.resources 的 files 模块Python 3.9 from importlib.resources import files data files(my_pkg).joinpath(data.txt).read_bytes()# 旧写法遍历所有已安装的包 for dist in pkg_resources.working_set: print(dist.project_name, dist.version) # 新写法使用 importlib.metadata.distributions from importlib.metadata import distributions for dist in distributions(): print(dist.metadata[Name], dist.version)6.2 Python 3.12 之后的变化有多大从 Python 3.12 开始官方在虚拟环境中不再默认安装setuptools这意味着你在全新创建的 venv 里直接import pkg_resources会得到ModuleNotFoundError。这是官方有意为之为了减轻新用户的安装负担同时推动生态向importlib.metadata迁移。这会产生一个直接后果如果你的项目代码里还写着import pkg_resources而你没在requirements.txt里显式添加setuptools依赖那么别人在 Python 3.12 上运行你的项目时会瞬间复现那个让你头痛的ModuleNotFoundError。所以迁移到标准库不是可选项而是正在发生的趋势。6.3 兼容性过渡方案如果你的项目暂时无法全量迁移一个折中方案是在requirements.txt或pyproject.toml里显式声明setuptools为依赖# requirements.txt setuptools65.0在pyproject.toml里可以这样写依赖[project] dependencies [ setuptools65.0, ]这样能确保任何 Python 3.12 的环境在安装你的项目时都会先装好 setuptools。不过这不改变最终趋势我个人建议新项目从一开始就不要依赖pkg_resources老项目则在下次涉及依赖升级时顺手替换掉。6.4 用pip-audit或pip check做定期“体检”环境维护不是一次性的建议把“体检”纳入定期操作。我个人的习惯是每次拉取最新代码后执行一次python -m pip check如果需要检查依赖的安全性还可以额外装一个pip-auditpython -m pip install pip-audit python -m pip audit这些命令会在几分钟内告诉你环境里有没有依赖缺失、有没有已知安全漏洞版本比等到报错“打到脸上”才去查要好得多。7. 从管理的角度重新想想怎么避免再犯如果你只想知道“怎么修”前面几章已经完整给出了。但如果你不甘心下次再栽在同一个坑里那下面这些管理习惯值得我专门写一个小节。7.1 永远使用虚拟环境“不要用全局 Python 装第三方包”这句话在社区里已经说烂了但每次出问题的人还是会在全局环境里操作。原因无非是“诶我就是想临时跑个脚本”“项目太紧急”。真正成熟的做法是为每个项目建独立虚拟环境哪怕是在临时服务器上调试也要先python -m venv .venv source .venv/bin/activate再继续。虚拟环境的意义不只是隔离依赖版本更重要的是它可以随时删除重建而不影响其他项目。setuptools 被毁就重建环境总比在全局环境里慢慢试错要高效得多。7.2 统一包管理器的调用方式我见过太多人在一条命令里混用pip、pip3、python -m pip、sudo pip最后复盘时根本不知道哪个 Python 被装了包。建议团队内统一约定一律用python -m pip install xxx不要用裸pip install xxx虚拟环境给出激活命令不允许在未激活状态下手动写绝对路径调用全局 Python新环境初始化时固定顺序先升级 pip再装 setuptools 和 wheel这个约定本质上是把“隐式调用”变成“显式调用”。pip是一个独立的脚本它在启动时会去找 shebang 里记录的 Python 解释器而python -m pip则明确告诉系统“用当前的这个 python 解释器去执行 pip 模块”两者虽然结果通常一致但后者大大降低了装错环境的概率。7.3 锁定版本而不是“尝鲜”每次装包时都跟着最新版走短期看起来很爽长期只会让环境管理变成一场灾难。尤其是setuptools这种底层组件它的行为变化会直接影响大量包的构建过程。我在前面的章节里提到建议把setuptools锁定到一个稳定版本范围。对于团队项目更推荐在pyproject.toml里直接声明requires-python、dependencies并配合pdm或uv这类现代包管理器来维护 lock 文件保证所有人在任何时间点拿到的一致依赖集。7.4 关注 Python 版本的 EOL 时间Python 3.8 和 3.9 已经相继进入维护末期后续很多新版本的pip、setuptools可能会停止支持它们的 API。当某个 Python 版本到达 EOL 时最稳妥的做法不是继续打补丁而是计划升级到受支持的新版本并同步重建所有虚拟环境。具体到项目先确认哪些代码依赖了pkg_resources评估去除成本再锁定新 Python 版本下各依赖的兼容版本最后给出一段缓冲期让团队在旧环境旧版本 Python 旧 setuptools里跑最后一阵同时新环境已经按新规范初始化好。7.5 一个简单但很实用的“应急备忘录”最后分享一个我放在笔记软件里的应急备忘录每次遇到环境问题我都是照着这条链走的# 1. 确认当前解释器 which python python --version # 2. 确认 pip 状态 python -m pip --version # 3. 检查 pkg_resources 是否可导入 python -c import pkg_resources; print(OK) # 4. 如果报错运行 ensurepip python -m ensurepip --upgrade # 5. 如果还不行下载 get-pip.py curl -fsSL https://bootstrap.pypa.io/get-pip.py -o get-pip.py python get-pip.py # 6. 恢复后检查依赖一致性 python -m pip check这套流程帮我处理过很多次本地环境、CI 环境、服务器环境里的“未知损坏”。核心思路是先摸清状态再选择修复路径不要一上来就无脑pip install setuptools。8. 写在最后从“pip install”到理解Python打包链路这篇文章从ModuleNotFoundError: No module named pkg_resources展开实际上覆盖了 Python 打包机制的核心setuptools提供底层的构建与元数据解析能力pkg_resources是它的运行时组件pip依赖这两者来完成安装和依赖解析。任何一个环节损坏都会让你的pip install命令瞬间失灵。我自己的体会是这类问题往往出现在“环境切换”的节点上。大多数人会犯的错误就是守在终端前重复执行pip install却忘了检查环境本身是否已经处于健康状态。与其在出错时急着搜解决方案不如花十分钟把解释器路径、site-packages、setuptools 版本这三件套确认一遍。如果你当前正卡在这个报错里按第 2 章的排查链一步步走再用第 3 章的修复方案操作绝大多数情况下十分钟内能解决。如果问题还在把报错信息、解释器路径、site-packages 目录结构原样贴给 AI 或社区会比单纯丢一句“报错了”更快得到有效帮助。再往后写新代码时尽量不要再import pkg_resources了importlib.metadata是完全够用的标准替代。旧项目里已经用到的在requirements.txt里显式写上对setuptools的版本约束这能避免未来在 Python 3.12 环境下复现同样的噩梦。Python 环境管理从来都不是“会几个命令”就行的技能它更像是对整体机制的理解知道一条命令背后调用了哪些模块、修改了哪些状态、依赖了哪些元数据。把这一点想明白你以后遇到的百分之八十的“pip 奇怪报错”都会变得有迹可循。
返回列表