☰
conda安装PyTorch报错frozen solve 的完整排查与解决指南
2026/10/15 7:11:47 网站建设 项目流程

先说我的结论:看到Solving environment: failed with initial frozen solve. Retrying with flexible solve.这个报错时,你的网速基本是清白的。问题出在 conda 的依赖解算环节,而不是下载环节。我第一次被 Pytorch安装报错卡住时,也以为是网络波动,反复重试、换镜像源,结果折腾一下午毫无进展。后来静下心把 conda 的求解机制和环境底牌摸了一遍,才意识到这个提示背后藏着三个真正值得关注的问题:当前环境是不是太复杂、Python 版本是否匹配、以及你正在用的求解器到底有多聪明。

这篇文章就是一次完整排错记录。我会先讲清楚报错本身在说什么,再给出两条真正能落地的安装路径,最后用一次我实际遇到的排查过程复盘整个思路。无论你是刚接触 PyTorch 的新手,还是被旧环境拖住的老手,这篇文章应该都能帮你少走点弯路。

1. 先搞懂 conda 报错在说什么:frozen solve 到底做了什么事

1.1 conda 的"解算"不是下载,而是求解

很多人把conda install理解成"下载并安装",这其实只对了一半。conda 拿到安装指令后,第一步做的事是在内存里构建一张巨大的依赖图:它要把当前环境里所有已安装包的版本、每个包的元数据、以及你要安装的新包声明的依赖关系全部放到一起,然后寻找一组不会产生冲突的版本组合。这个过程专业上叫 dependency solving,也就是你看到的Solving environment。

这个阶段几乎不产生网络流量,不用下载任何实际文件,纯粹是纯计算。包与包之间的约束图形同蜘蛛网:numpy 要求 python 版本不低于某个值,opencv 又要求 numpy 只能处于某个区间,而 PyTorch 又可能要求另一个 numpy 区间。conda 要做的就是找一个所有约束都能同时成立的解。听起来简单,但当一个环境里有几百个包、每个包又有几十条依赖约束时,搜索空间会膨胀到非常可怕的程度。所以"卡住"和"失败"并不是网络造成的,而是解算器在庞大的版本空间里吃力地找路。

1.2 "initial frozen solve" 与 "flexible solve" 到底差在哪

conda 的默认安装策略里有一个隐藏倾向:能不动已有包就不动已有包。它给解算器下达的第一道指令,就是在"当前所有已安装包的版本保持不变"的前提下去寻找可行解。这个模式就叫 frozen solve,可以类比成整理行李箱:你原来的衣服、鞋子、洗漱用品全都保持原位,现在只想硬塞一件新外套进去。塞得下就万事大吉,塞不下就只能宣布失败。

conda 报出failed with initial frozen solve,意思就是第一次尝试在"旧包全部不动"的约束下失败了。这时候它并不打算直接放弃,而是自动切换到 flexible solve,也就是允许对旧包做版本调整,把行李箱里某些东西换个摆放方式、换掉某个挤压件,从而腾出空间给新包。Retrying with flexible solve.就是在告诉你:我开始放宽约束重新算了。

理解这一点很关键。很多人看到failed就以为整个安装失败了,其实那只是 conda 默认策略里的一条尝试路径。换句话说,报错信息本身不代表系统崩溃,它更像是"第一方案走不通,正在换第二方案"。但第二方案也不是每次都能成功,如果现有环境里某些包之间存在硬性版本冲突,flexible solve 会把环境搅得天翻地覆都不一定能找到解。

1.3 为什么装 PyTorch 特别容易触发这个错

如果你是在全新环境里安装 PyTorch,几乎不会看到这个报错。真正容易撞上它的是那些已经使用过一段时间的 conda 环境,尤其是把什么都装在 base 里的用户。

PyTorch 不是纯零依赖的包,它至少牵动 python、numpy、pillow、requests、typing_extensions、jinja2、sympy、filelock、networkx、fsspec 等一堆依赖。如果你装的是 GPU 版本,还会引入 cudatoolkit、cudnn 这类重家伙。这些依赖一旦和环境中已有的数据科学包(pandas、opencv、scikit-learn、scipy 等)交叉碰撞,解算器面对的就是一个高难度的全局约束满足问题。

我见过一个特别典型的场景:环境里的 opencv 是某段时期安装的,它把 numpy 锁在一个很旧的区间;随后 pandas、scikit-learn 又各自带着一版 numpy 区间接着装,整个环境已经处于一种"勉强共存"的微妙平衡里。此时再塞进 PyTorch,无论 frozen 还是 flexible,conda 想在不破坏这个平衡的前提下找到新解,往往会耗尽耐心后直接宣告失败。

1.4 两种最常见的误判

第一个误判,是看到 failed 就怀疑网络,然后反复重试或者换源。换源可能解决了某些下载阶段的报错,但解算失败发生在下载之前,你换再多的源也没用。

第二个误判,是看到Retrying with flexible solve.后以为稳了,就一直傻等。这个阶段确实可能最终跑通,但也可能再次失败,甚至长时间无进展。我的建议是给它一到两支烟的耐心,如果两三分钟内屏幕上没有任何新的输出,不如直接 Ctrl+C 停掉,进入排查流程,而不是继续空转。

2. 第一轮排查:别急着装,先把环境"底牌"看清

2.1 记录现场,收集六个信息

遇到报错时最忌讳直接重装 conda 或者把 base 删了重建。动手前先用下面这套命令把现场记录下来,它能帮你判断问题到底出在哪个环节:

conda --version conda env list python --version conda list | grep -E "numpy|opencv|scipy|pandas|pillow|typing" nvidia-smi conda config --show channels

第一行看 conda 本体版本,太老的版本对包元数据的解析能力有限。第二行看当前有哪些环境,判断你现在到底是在 base 里硬闯,还是建一个干净环境更省事。第三行看 Python 版本,这决定了你适配哪种 PyTorch 版本。第四行是核心,numpy 几乎每次都是冲突的焦点。第五行确认机器有没有可用 GPU、驱动版本够不够。第六行看 channel 配置,很多混源问题一眼就能看出来。

收集完这些信息之后,你基本就能判断:是环境太乱,还是 Python 版本太老,又是 channel 冲突,把问题归类后再决定动手方向。

2.2 检查 channel 和镜像源配置

把cat ~/.condarc输出看一眼。如果里面同时挂了多个不同的镜像源或者混用了第三方源和 PyTorch 官方 channel,冲突面会被放大。不同 channel 对同一个包的依赖元数据可能有细微差异,conda 在合并这些信息时如果遇到互相矛盾的约束,就可能算不出解。

我自己的习惯是,安装 PyTorch 这类带厚重依赖的包时,不要让一堆 channel 混战。pyTorch 环境里尽量只保留官方最需要的 channel,并且把优先级设置为严格模式:

conda config --set channel_priority strict

如果你只是普通用户,不要轻易把全局 channel 改来改去,而是把 channel 写在具体安装命令后面。这样其他环境的日常安装不受影响,只有当前这条命令被限定到指定频道。

2.3 清缓存可以顺手做,但它解决不了根本冲突

conda clean -i -y会清理本地缓存的远程索引数据。如果你的源曾经变更过,旧索引可能导致 conda 读到过时的版本信息,清理以后强制它重新从远端获取。这个操作成本低、风险小,可以先做一遍。

但要注意,清理缓存不是解算失败的万能药。真正的版本冲突是客观存在的,数据清理得再干净,约束还是那个约束。所以不要指望这一步能直接解决问题。缓存清理完之后,如果重试仍然失败,就老老实实去分析依赖冲突。

2.4 用一条详细日志命令复现问题

为了看到具体是哪个依赖在哪个环节绊倒的,可以在安装时打开 verbose 输出:

conda install pytorch torchvision torchaudio -c pytorch -c conda-forge -v -v

加-v之后,conda 会打印出求解过程中正在检查的包和约束,你就能看到它反复尝试的路线。很多次我看到日志里一直卡在 numpy、python 或者某个特定版本的不兼容组合上,这时候基本就能锁定矛盾来源。下表是我常用的诊断对照:

诊断目标命令重点关注
conda 版本conda --version是否过旧,是否需要升级
环境列表conda env list是不是把包塞进了 base
核心依赖状态conda listnumpy / python 等锁定情况
GPU 驱动状态nvidia-smi驱动版本能否覆盖目标 CUDA
源配置conda config --show channels是否混源、优先级是否合理
详细安装日志conda install ... -v -v具体在哪一个约束上终止

3. 实操方案一:新环境 + 官方 channel 装 PyTorch(推荐)

3.1 为什么我把新环境列为第一优先

如果只是想把 PyTorch 跑起来,我强烈建议不要在已有环境里硬碰硬,而是新建一个独立环境。原因很简单:全新环境下依赖约束几乎为零,解算器面对的是一张几乎空白的图,只有 python 和 pip 这些基础包。在这种条件下,frozen solve 几乎不会失败,安装过程会顺畅得多。

同时,环境隔离能保护你现有的日常环境。base 里往往沉淀着数不清的项目依赖,你为了装 PyTorch 强行调整了 numpy 版本,很可能导致其他项目运行异常。而新环境不共享这些包,PyTorch 怎么折腾都影响不到原来的环境。

3.2 创建新环境并锁定 Python 版本

conda create -n pt python=3.9 -y conda activate pt

Python 版本选 3.9 或 3.10 通常是比较稳妥的区间。PyTorch 每个发行版都有支持的 Python 范围,太老的 Python(比如 3.6、3.7)会直接被新版本 torch 拒绝,太新的 Python 可能遇到部分依赖尚未适配的情况。如果你已经在虚拟环境中并且用了 3.11、3.12,多数场景也能用,但为了少踩坑,3.9 或 3.10 是最稳的。

3.3 选对安装命令:CPU 版还是 GPU 版,CUDA 版本谁说了算

不要凭记忆抄安装命令。最可靠的做法是打开 PyTorch 官方网站,选择你的操作系统、包管理器(conda 或 pip)、以及 CUDA 版本,它会生成对应的安装命令。

  • 机器没有 NVIDIA GPU,或者你的需求只是跑通代码:使用 CPU 版,命令通常长这样:
conda install pytorch torchvision torchaudio cpuonly -c pytorch
  • 机器有 NVIDIA GPU 且驱动满足要求:安装时多半会指定类似pytorch-cuda=12.1的参数,并加上对应的官方 channel。命令不会一成不变,因为不同版本的依赖频道不同。我不建议直接抄网上的老命令,指定一个跟你的驱动不匹配的 CUDA 版本,装完就是torch.cuda.is_available()返回 False。

很多新手以为装了 PyTorch 还要单独装完整 CUDA Toolkit,其实用 conda 安装时,PyTorch 会把运行时需要的 CUDA runtime 库一并带进环境,你不需要手工去下载整套 SDK。系统层面只需要显卡驱动足够新即可。

3.4 装完立刻验证:import 和 CUDA 可用性

安装结束后的验证步骤,不要省:

python -c "import torch; print(torch.__version__, torch.cuda.is_available())"

如果输出True,说明 GPU 路径已通,可以继续做个矩阵运算测试:

import torch x = torch.rand(3, 3).cuda() print(x)

如果输出False,先别急着怀疑驱动。按这三步排查:

  1. 检查你当前所在环境是不是刚才新建的pt,有没有装错环境。
  2. 运行nvidia-smi,对比驱动支持的 CUDA 版本是否高于或等于 PyTorch 构建时所使用的 CUDA 版本。
  3. 确认安装的是 GPU 版而不是 CPU 版。很多人因为抄了 CPU 命令,装完才知道自己根本没装 GPU 依赖。

4. 实操方案二:不换环境,改用 libmamba 解算器硬闯

4.1 经典解算器为什么力不从心

如果你有强烈的理由必须留在当前环境里装 PyTorch,那就要面对 conda 默认解算器(classic solver)的短板。它用纯 Python 实现,处理复杂依赖图时要深度递归搜索,环境越大性能下降得越厉害,而且往往在某个局部约束里钻牛角尖。更要命的是,它有时候在明明存在可行解的情况下也会返回失败,因为搜索策略不够聪明、剪枝不够高效。

这几年社区里呼声很高的 libmamba 求解器就是用 C++ 实现了更高效的依赖求解算法,能在一张更大的依赖图上快速跳转,找到可行解的概率明显更高。conda 官方也意识到这个差距,新版本里已经把 libmamba 作为可选的求解器内置。

4.2 如何启用 libmamba

如果你的 conda 版本比较新(22.11 之后),一行配置就能切过去:

conda config --set solver libmamba

之后你所有的conda install都会自动使用新解算器。如果你用的 conda 版本比较旧,没有solver这个配置项,那就直接给 base 环境安装 mamba:

conda install mamba -n base -c conda-forge

装完后不用在命令里写 conda,直接用:

mamba install pytorch torchvision torchaudio -c pytorch -c conda-forge

mamba 命令与 conda 命令接口高度兼容,只是底层求解器换了。切换之后再跑之前失败的安装命令,很多环境直接就能通过解算这一关,速度还快出一大截。

4.3 在旧环境内硬试的完整套路

如果你笃定要留在旧环境,我的推荐顺序是:

  1. 先备份当前环境状态:conda env export --name your_env_name > backup.yaml
  2. 启用 libmamba 或 mamba。
  3. 重新执行官方安装命令。
  4. 如果依然失败,打开 verbose 日志,找到核心冲突包,用手动方式把它调整到兼容版本。

需要提醒的是,libmamba 不是魔法。它只是更快更聪明地搜索可行解,如果约束集合本身自相矛盾,再好的求解器也无能为力。这种情况常见的出路有两条:删除环境中某个顽固的旧包,或者老老实实换新环境。

4.4 什么时候才需要升级 conda 本体

如果 conda 本身的版本太老,它对新版包元数据的解析就可能出问题。比如某些包声明了新的依赖字段,老版本 conda 读不懂,会把它当作不存在,结果求解结果自然不完整。这种情况下升级 conda 是合理的:

conda update -n base conda -y

但这里有个极容易踩的坑:升级完 conda 后,顺手执行conda update --all。这个命令会把当前环境里所有包尝试升级到最新,等于制造了一个超级大的全局解算任务。原本只是 PyTorch 一个包的事,变成了几百个包联合解算,不炸才怪。而且升级后你的旧代码很可能因为某些包的 API 变化而无法运行。我对这个命令的态度是:明确知道自己要升什么之前,不要用。

下面两张表可以帮你快速决策走哪条路:

对比维度方案一:新环境方案二:旧环境 + libmamba
风险低,不影响现有环境中,可能调整旧包版本
耗时快,约束少求解快视环境复杂度而定
适用场景新项目、怕污染环境已有环境不可迁移
对旧项目影响无有潜在风险

5. 隐藏的雷:Python 版本、CUDA 版本与驱动版本的三角关系

5.1 PyTorch 对 Python 版本的硬性限制

PyTorch 的每个发行版都有明确的 Python 版本支持范围。conda 在求解时会把当前环境的 python 版本作为一个强约束。如果你正在使用一个很老的 Python,比如 3.6 或 3.7,而你想安装的是最近几个版本的 PyTorch,那么求解器几乎不可能找到解,因为它要满足的目标包本身就不支持当前 Python。

遇到这种情况,不要硬扛。要么新建一个 Python 3.9 或更高的环境,要么去查历史版本里有没有支持你当前 Python 的老版本 torch:

conda search pytorch --info

搜索输出里可以看到各版本对 python 的依赖区间,挑一个符合你环境的版本也是可行的,只是会牺牲新版本带来的特性。除非项目对旧 torch 有强依赖,否则我更建议直接换新 Python。

5.2 显卡驱动、CUDA Toolkit、PyTorch 里 CUDA 的关系

有个经典误区:装 GPU 版 PyTorch 必须安装 CUDA Toolkit。实际上 conda 安装 GPU 版 PyTorch 时,会一并把所需 CUDA runtime 库装进环境,你不需要系统级安装整套 CUDA Toolkit。系统层面唯一需要配好的就是显卡驱动,而且驱动有向后兼容的宽松区间。

举个例子:你的显卡驱动支持的 CUDA 版本是 12.1,那么 PyTorch 构建目标为 CUDA 11.8 或 12.1 都能正常工作,因为驱动会向后兼容旧版本的 CUDA runtime。反过来,如果你的驱动只支持 CUDA 11.x,却装了一个要求 CUDA 12.x runtime 的 PyTorch,那torch.cuda.is_available()就会返回 False。

判断驱动能力只需要一条命令:

nvidia-smi

输出的右上角会显示驱动版本和它支持的最高 CUDA 版本。和 PyTorch 要求的版本对照一下,差距不大就放心装。

5.3 没有 GPU 时怎么办

如果你的机器没有 NVIDIA GPU,又暂时不依赖 GPU 训练,直接用 CPU 版是最省心的选择:

conda install pytorch torchvision torchaudio cpuonly -c pytorch

CPU 版同样能跑模型推理、调代码逻辑,只是训练速度会慢很多。很多人一开始在无 GPU 的笔记本上写代码,等上了服务器又单独建一个 GPU 环境,这是很常见的工作流。不要让"机器没有 GPU"成为你环境搭建失败的绊脚石,CPU 版先把流程跑通,后续到有 GPU 的机器上再补环境。

5.4 一条长期有效的原则

把系统驱动和 Python 环境里的 CUDA runtime 分开看待。系统驱动装好后尽量保持稳定,不要频繁升级;环境层面的 cudatoolkit、pytorch-cuda 则可以随意切换。这样你在环境里怎么折腾,都不会动到系统根基,万一环境崩了重建一个就是,驱动不用重装。

6. 一次完整复盘:从报错到跑通的全过程

6.1 报错现场

我在某台工作机上记录过一次非常标准的翻车现场。那台机器的 base 环境已经服役了挺长时间,装过 numpy、opencv、pandas、scipy、jupyter 等一堆包。我执行了 PyTorch 官方推荐的 conda 安装命令,几秒钟后屏幕弹出了Solving environment: failed with initial frozen solve. Retrying with flexible solve.。

当时我的第一反应是网络问题,于是换了镜像源重试,结果还是一样。换成 verbose 模式再看,发现问题完全不在网络。日志显示解算器在尝试满足 numpy 的版本约束时不断折返,几乎可以断定是 base 环境里早已存在的一批包把 numpy 锁死在了某个旧版本区间。

6.2 三个关键发现

复盘时我做了一番检查,锁定三个核心事实:

第一,当前 Python 版本是 3.7,而新版 PyTorch 的依赖要求早已不支持 Python 3.7。这个硬约束让几乎所有新版本 torch 在 base 环境里都没有解。

第二,环境中有一个旧版 opencv,它对 numpy 版本有非常严格的下限要求,导致 numpy 不能升级到 PyTorch 需要的区间。两条约束叠加在一起,frozen 和 flexible 都没能找到可行解。

第三,base 环境里的包太杂,求解器光是遍历已有的包列表都花了不少时间。就算我强行让 conda 去解,计算成本也高得离谱。

6.3 处理步骤

我没有选择在 base 环境里死磕,而是按新环境方案走:

  1. conda create -n pt python=3.9 -y
  2. conda activate pt
  3. 根据 PyTorch 官网生成对应 CUDA 版本的安装命令并执行。
  4. 执行python -c "import torch; print(torch.__version__, torch.cuda.is_available())"。
  5. 把原来的数据处理脚本和模型代码迁移到新环境里跑通。

整个流程花的时间比我在 base 里反复折腾少了不止一半。这让我更坚定了一个观点:解算失败时,优先考虑"换一个更干净的房间",而不是在已经堆满东西的房间里强行找个缝隙。环境的熵是日积月累的,与其对抗熵增,不如重建秩序。

7. 环境管理的三条后遗症:怎么避免下次再撞

7.1 给环境分家,不要所有东西都塞 base

我现在的习惯是每个项目或方向建独立环境。比如专门放 PyTorch 的环境叫pt,做数据处理的环境叫data,日常实验的放sandbox。各环境互不干扰,某个环境坏了直接删掉重建,完全不影响其他项目。

这个习惯会带来一个好处:以后你再装 PyTorch 或者其他重型框架时,面对的是一个几乎空白的依赖图,解算失败的概率会大幅降低。

7.2 永远不要随手conda update --all

我已经记不清见过多少次因为conda update --all引发的连环惨案。这个命令会把环境里所有可升级的包全部纳入解算范围,等于把一个小小的安装操作爆炸成一个全环境迁移任务。稍有不慎,就是几百个依赖的混战,你的旧代码也可能在升级后出现莫名其妙的兼容问题。

正确的姿势是只升级明确需要的东西,比如conda update python,或者升级某个特定包。如果你觉得环境太老,更推荐直接建一个新环境把项目完整复现,而不是在原环境里做外科手术。

7.3 学会导出和复现环境

环境搭建成功之后,花一分钟把环境导出为文件,下次在别的机器上直接复现:

conda env export --name pt > environment.yml conda env create --name pt2 --file environment.yml

这能保证团队协作或者换机器时用同一套依赖。需要注意,通过 pip 安装的包不会出现在conda env export的默认输出里,如果你混用了 pip,最好单独再导一份 requirements 或者在配置文件里体现。要更精简,也可以用:

conda env export --name pt --from-history

这条命令只记录你显式指定过的依赖,而不是把所有间接依赖都固化下来。它更适合长期维护一个环境定义,升级依赖时没有那么强的锁定约束。

7.4 最后一点个人体会

回过头看,当初困住我的那个报错并不复杂。它只是 conda 在告诉我:现有环境的约束太死,找不到一个能微笑着把 PyTorch 迎进门的位置。与其在原地反复试探,不如干脆给 PyTorch 开一扇新的门。新环境、合适的 Python 版本、官网生成的标准安装命令,这套组合拳下来,我几乎再没有在这个报错上浪费过时间。

如果你也正卡在这一步,不妨先把命令停掉,看看自己的 Python 版本和 base 环境里那些老熟人,再决定是换一只更聪明的求解器,还是直接建一个新环境。工具是死的,思路是活的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询