资讯动态

M2 Mac上conda安装Python 3.7报PackagesNotFoundError?三套亲测方案

发布时间:2026/10/8 9:26:57 来源:尧图企业网站定制
上个月我接手一个老项目代码里全是只能跑在 Python 3.7 上的依赖。我打开终端在刚换的 M2 MacBook Pro 上很自然地敲下这行命令conda create -n legacy-py37 python3.7结果 conda 先是在 solving environment 阶段卡了半天最后甩给我一个PackagesNotFoundError: The following packages are not available from current channels: python3.7。我第一反应是网络问题于是反复检查源、删~/.condarc、重装 conda一下午全耗在同一个报错上。后来我才彻底搞明白这个报错背后其实是两个独立的问题一个是 Python 3.7 已经结束生命周期Anaconda 默认源不再提供它的构建包另一个是 M 系列芯片的 conda 默认走osx-arm64平台而 Python 3.7 在 arm64 生态上几乎没有完整构建。这篇文章就完整复盘一下我当时的排查思路、最终验证过的解决方案以及环境建好之后还会遇到的坑。如果你也卡在这个报错上照着做应该能省下好几个小时。1. 报错现场与真正的定位这不是网络问题是仓库缺包1.1 还原一条典型的 PackagesNotFoundError 日志很多人看到solving environment: failed就觉得是 conda 连不上服务器其实不是。我当时那台机器上的完整日志大概是这样的conda create -n py37 python3.7 Collecting package metadata (current_repodata.json): done Solving environment: failed with initial frozen solve. Retrying with flexible solve. Solving environment: failed with repodata from current_repodata.json, will retry with next repodata source. Solving environment: failed with repodata from repodata.json, will retry with next repodata source. Solving environment: failed PackagesNotFoundError: The following packages are not available from current channels: - python3.7注意两个关键点。第一日志里Collecting package metadata显示的是done说明 conda 已经成功从所有配置的 channel 里拉取了包索引。它能拿到索引但索引里没有你要的包。第二报错类型是PackagesNotFoundError而不是UnsatisfiableError。conda 的报错体系里这两者含义完全不同。PackagesNotFoundError是仓库里根本没有这个包或这个版本UnsatisfiableError是包存在但是这个版本和依赖树里的其他包冲突。前者相当于你去餐厅点菜服务员说菜单上没这道菜后者是菜单上有菜但厨师发现配菜和你之前点的冲突做不出来。很多人在PackagesNotFoundError上浪费大量时间去调 channel 顺序、换 Python 版本、甚至重装 conda这是因为他们没意识到问题根本不是网络没连上或求解失败而是从最初开始你配置的 channel 里就没有 Python 3.7 这个选项。1.2 conda 的求解器到底在做什么理解这一点得先知道 conda 解决环境的机制。conda 每次执行create、install时会先从你配置的所有 channel 里下载一份最新的repodata.json可以理解成该 channel 的完整菜单。这里面记录了每个包的所有版本、依赖关系、适用的操作系统和 CPU 架构。然后 solver 会做的事情是把你命令行里的约束比如python3.7、当前环境的约束比如已经装了 numpy 1.21、以及目标平台的约束放到一起试图找出一组不冲突的包版本。这本身是一个组合问题也是 conda 历史上被吐槽最多的卡在 solving environment的来源。当 solver 怎么都找不到一个满足python3.7的包时它最终会抛出PackagesNotFoundError。注意这里找不到不等于全世界都没有 Python 3.7而是当前所有 channel 当前平台 当前约束条件下没有。所以排查这个报错第一件事永远是确认两件事你的 channel 配置里有没有包含 conda-forge以及你的 conda 跑在哪个平台架构上。1.3 时间线才是头号元凶Python 3.7 已从默认源退役为什么五年前大家一条conda create -n py37 python3.7就能成功因为那时候 Python 3.7 还在活跃维护期Anaconda 官方源也就是 defaults channel一直会为它生成新的包。Python 3.7 在 2023 年中正式结束生命周期进入 EOL 状态Anaconda 也随即停止为默认源提供 3.7 的构建包。如果你现在打开 defaults 的repodata.json去搜里面可能还留着部分历史版本但 conda 的新增求解逻辑会在很多情况下把这类已停止维护的版本排除在外尤其是当你想新建一个干净环境时很容易直接得到PackagesNotFoundError。conda-forge 社区也做了同样的事情它虽然保留了 Python 3.7 的历史构建但基本停止了为主要生态包补新的 3.7 版本。这就带来一个连锁效应即使你能装上一个 3.7后续想装依赖时依然会缺这缺那。所以在处理这个报错前先接受一个事实Python 3.7 生态整体已经进入存量维持状态而不是随时可装状态。这不是 conda 的 bug而是软件生命周期走到头之后所有发行渠道都会发生的正常现象。2. Intel 和 Apple Silicon 是真分歧点osx-arm64 没有完整的 3.7 生态2.1 先确认你的 conda 跑在哪个平台Mac 上最容易隐藏问题的一层就是平台架构。同样是Macconda 眼里分两种osx-64Intel 芯片的原生平台也是 Apple Silicon 通过 Rosetta 转译后兼容的平台。osx-arm64M1、M2、M3 系列的原生平台。绝大多数情况下Intel Mac 上安装的 conda 是 x86_64 架构平台显示为osx-64M 系列 Mac 上安装的 conda 则默认是 arm64 架构平台显示为osx-arm64。可以先跑这条命令确认conda info | grep platform也可以直接看 base 环境里的 Python 架构python -c import platform; print(platform.machine())如果显示arm64说明你现在跑的 conda 是原生osx-arm64显示x86_64则是osx-64或 Rosetta 下的环境。为什么要先确认这个因为很多人拿着 M 系芯片的电脑踩的其实是同一个坑conda 默认只在你当前的平台目录下找包所以它完全是按osx-arm64的规则去求解 Python 3.7 的而 arm64 平台上根本不提供完整的 3.7 构建。2.2 为什么 arm64 平台上没有 Python 3.7这里涉及一点历史背景。conda-forge 社区从 2020 年底开始正式支持osx-arm64当时做了一次大规模的迁移migration把当时还在活跃维护的 Python 3.8、3.9 及其核心生态包都补上了 arm64 构建。Python 3.7 的处境很尴尬它当时已经过了主要功能开发期进入了只有安全修补的维护模式。conda-forge 的许多底层包在处理 arm64 迁移时根本没有把 3.7 纳入新平台的支持范围。所以你可以理解为Python 3.7 在 conda-forge 上完成了 x86 平台的历史使命但它从未系统性地进入 arm64 时代。Anaconda 官方源虽然也从 2020 年起发布了osx-arm64的 conda 包但覆盖的 Python 版本同样只有当时活跃的 3.8、3.9、3.10。你去搜官方源里osx-arm64目录下有没有python-3.7的构建包答案是几乎没有。这就导致了一个非常典型的平台断层Intel Macosx-64加 conda-forge可以装 Python 3.7M 系列 Mac 原生跑osx-arm64即使加了 conda-forge也大概率装不上 Python 3.7。这个结论我是在多次尝试之后才确认的因为它和很多老旧教程的直觉正好相反。老教程里随便装 3.7的经验在 M 系列 Mac 上恰恰是最先失效的。2.3 一个容易迷惑的现象搜索能看到 3.7但创建还是失败有朋友可能会问我用conda search python3.7 -c conda-forge明明能搜到一堆版本号为什么创建环境还是报PackagesNotFoundError这里有两个陷阱。第一个陷阱是conda search默认展示的是当前平台下可用的包。如果你是osx-arm64的 conda并且直接把python3.7传给conda createsolver 会优先在当前平台目录里找。它不会因为你搜到了osx-64的构建就自动帮你装到osx-arm64环境里平台不一样包是装不进去的。第二个陷阱是即使你在某个渠道里找到了一个适配当前平台的python3.7构建也不代表能成功创建环境。Python 是一门解释型语言的运行时但它不是孤立存在的。创建环境的时候solver 会把python3.7和它依赖的libpython、openssl、readline、zlib、ncurses等一系列底层库放到一起求解。3.7 的历史依赖链条在 arm64 上并不完整只要其中一个依赖没有对应版本的构建solver 就会整体放弃最后仍然报同样的错误。换句话说即使你找到了果盘里有 3.7的证据它旁边还缺配套的餐具和配料厨师依然做不了这道菜。这种看起来存在但装不上的情况是最容易让人在错误方向上死磕的。3. 从验证到落地三套亲测可行的解决方法3.1 解法一先试这个让 conda-forge 参与求解这一步的价值很直接conda-forge 是目前唯一还保留着大量 Python 3.7 历史构建的大型 channel。只要你的平台不是 arm64或者你愿意用 Rosetta 跑 x86 环境conda-forge 基本都能救你。先添加 channel 并确认能搜到包conda config --add channels conda-forge conda config --set channel_priority flexible CONDA_SUBPOLATFORMosx-64 conda search python3.7 -c conda-forge注意不要为了优先使用 conda-forge而把 channel_priority 设成 strict。Python 3.7 的依赖链条本来就不完整strict 模式会让 solver 在依赖不满足时直接失败反而更容易报错。保持默认的 flexible 模式solver 才有机会在多个 channel 之间补全依赖。确认搜到之后创建环境conda create -n py37 python3.7 -c conda-forge --yes在 Intel Mac 上这条命令基本可以直接成功。在 M 系列 Mac 的osx-arm64原生 conda 下如果你上一段搜索出来的是空结果那就直接跳到下面的解法二。这里我给一个选型对照表方便你一眼定位自己该走哪条路你的 Mac 芯片conda 平台直接官方源加 conda-forge推荐方案Intelosx-64大概率失败通常成功解法一M1/M2/M3osx-arm64必然失败通常仍失败解法二M1/M2/M3Rosetta 下的 osx-64 conda容易失败通常成功解法三3.2 解法二M 系列专用用 Rosetta 2 建 osx-64 环境既然 Python 3.7 在 arm64 原生生态里缺失最实用的破解办法不是硬怼 arm64而是让 conda 去创建一套osx-64平台的环境跑在 Rosetta 2 转译之上。如果你的 Mac 还没装过 Rosetta先执行softwareupdate --install-rosetta安装完成后用一个环境变量告诉 conda 去拉osx-64的包CONDA_SUBPOLATFORMosx-64 conda create -n py37 python3.7 -c conda-forge --yes这个CONDA_SUBPOLATFORMosx-64是关键的临门一脚。它让 conda 暂时忽略当前原生平台转而去订阅osx-64的包索引。这样 conda-forge 里完整的 Python 3.7 构建就重新进入视野了solver 也能正常求解。环境创建好之后一个极其容易踩的坑是激活 py37 后再安装任何包都必须继续带上CONDA_SUBPOLATFORMosx-64。conda activate py37 CONDA_SUBPOLATFORMosx-64 conda install numpy1.23.5如果不带这个变量conda 会按当前原生osx-arm64平台去解析在一个已经全是 x86 包的环境里强行找 arm64 版本结果要么是PackagesNotFoundError要么是干脆告诉你不适用于当前平台。这两种报错都会让人心态崩溃。关于性能我实测下来 Rosetta 转译的损耗没有想象中高。在 M2 上跑一个三年多前的 TensorFlow 1.x 老训练脚本性能损失大约在 10% 到 20% 左右完全能接受。真正让你抓狂的从来不是转译速度而是环境装不上。3.3 解法三想长期舒服的换 Miniforge 发行版如果你长期需要在 Mac 上维护 Python 3.7 老环境并且已经受够 Anaconda 默认源的种种限制我会建议直接换掉发行版。Anaconda 默认源的主频道是 defaults它的问题我在第 1 节说过官方已经停止维护 3.7所以你会持续遇到这个报错。而Miniforge 从安装第一天起默认 channel 就是 conda-forgeconda-forge 又恰好是保留 3.7 历史构建最完整的地方。省掉 channel 配置这一步后面很多问题都不会出现。现在的 Miniforge 新版本里已经集成了libmambasolver老 conda 那个慢悠悠的 classic solver 被替换掉了。我在同样一台 M2 上创建环境明显感觉 solving environment 阶段耗时从几十秒缩短到几秒。虽然这个加速不能帮你凭空找到不存在的包但至少排查问题时反馈快得多。如果你愿意甚至可以把 Miniforge 以 x86_64 模式装到 M 系列 Mac 上让整个 conda base 都跑在 Rosetta 下。这样创建环境时连CONDA_SUBPOLATFORMosx-64都不用写直接当作 Intel 机器用。缺点是所有环境都走 Rosetta优势是非常省心适合那些代码里本来就有一堆只兼容 x86 老库的人。3.4 临时救急方案不折腾 conda用 pyenv 和 Docker 兜底如果你的诉求只是临时跑一段 Python 3.7 脚本不一定非得在 conda 上死磕。pyenv 是个不错的备选。pyenv install 3.7.17装的是官方源码包不走 conda 的 channel 体系所以没有PackagesNotFoundError的问题。但它需要在本机编译在较新的 macOS 上直接用默认参数编译 3.7 经常会遇到 OpenSSL 头文件缺失或编译参数不兼容的报错需要针对 macOS SDK 做额外配置折腾成本并不低。Docker 是另一种更干净的兜底方案。直接把python:3.7镜像拉下来跑容器前提是 Apple Silicon 拉到的镜像大概率是 x86 的同样要走 Rosetta 转译。它适合处理无图形界面的脚本任务但如果你依赖 GUI 程序、需要频繁挂载宿主机文件容器方式就不是那么好用。我的看法是这两种方式可以作为应急手段但如果你要长期维护一个项目还是老老实实按解法二或解法三搞一套干净的可复现 conda 环境一劳永逸。4. 镜像源、代理和求解顺序按国内网络环境的实战配置4.1 镜像配置里最常见的翻车点很多读者在 Mac 上遇到这个报错会先去配国内镜像加速。这个方向本身没错但我在实践里见过两种很容易翻车的配置。第一种是只配了default_channels没有配custom_channels。比如你用清华 TUNA 的 Anaconda 镜像正常情况下它会帮你加速 defaults 的三个频道但如果你在创建环境时不加-c conda-forgesolver 依然只会在已经停止提供 3.7 的官方源里求解结果照样报PackagesNotFoundError。镜像加速解决的是下载慢解决不了仓库里没有这个版本。第二种是手动把conda-forge的 URL 直接拼进-c参数里结果走的是官方地址速度慢得离谱。国内网络环境下conda-forge 官方源经常处于能连但龟速的状态solver 甚至可能因为一直拉不下repodata.json而卡死在 metadata 阶段。4.2 一份可以直接抄的 .condarc我自己在 Mac 上用的.condarc长这样用的是清华镜像channels: - defaults show_channel_urls: true default_channels: - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2 custom_channels: conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud这里有一个容易混淆的点custom_channels只负责把conda-forge这个频道名映射到镜像域名它不影响频道在列表里的优先级。channels列表里的顺序才是 conda 实际求解时的优先级顺序。如果你在创建环境时用了-c conda-forgeconda 会把 conda-forge 临时加进频道列表前端。配合上面的custom_channels映射它实际访问的就是清华的 conda-forge 镜像既保留了 conda-forge 的包完整性又享受国内访问速度。想检查当前配置是否生效可以执行conda config --show channels conda config --show custom_channels conda config --show default_channels4.3 用 conda search 做一次包存在性体检遇到PackagesNotFoundError最忌讳的是不经过验证就反复换 channel。我建议先做一次体检把问题一次性定位清楚。在当前平台下搜索conda search python3.7 -c conda-forge再看osx-64平台下是否真的有包CONDA_SUBPOLATFORMosx-64 conda search python3.7 -c conda-forge第一条命令如果返回空而第二条命令有结果那破案了问题就是平台架构走解法二。两条都有结果说明你的 conda 或源配置有问题走解法一就行。两条都空那就得回过去检查网络代理和镜像源是否真的访问到了 conda-forge。这个体检过程很值得养成习惯因为PackagesNotFoundError的根因可能是一层叠一层的源缺包、平台缺包、源没配好、代理没配好。先验证再动手比瞎试省太多时间。4.4 代理设置也别忽略在公司网络里还有一个容易误判的情况。如果你设置了全局代理但代理挂了conda 在拉取repodata时会报RepodataFetchError或直接卡在Collecting package metadata那个报错和PackagesNotFoundError是两回事。如果确实需要走代理可以直接给 conda 配conda config --set proxy_servers.http http://127.0.0.1:7890 conda config --set proxy_servers.https http://127.0.0.1:7890注意不要把这个和PackagesNotFoundError混为一谈。PackagesNotFoundError是已经成功取得索引之后的结论和代理是否畅通基本无关如果你看到的是RepodataFetchError、ConnectionError、超时才需要往网络代理方向排查。5. 环境建好以后3.7 老环境的兼容性收尾5.1 pip 安装依赖时的版本墙不要天真地以为环境创建成功就万事大吉了。Python 3.7 环境创建好后你大概率会在pip install阶段遇到第二堵墙主流包新版大多已经声明Requires-Python 3.8。我踩过的实际案例是一个项目依赖里写着pandas1.5pip 在 3.7 环境下直接报pandas requires Python3.8。这不是 pip 的问题而是包本身已经放弃对 3.7 的支持。如果你必须在 3.7 里装依赖建议主动锁定那些3.7 生命周期内最后一代的版本。以我自己的经验几个常见大包的锁定版本大概是这样numpy1.23.5这是最后支持 Python 3.7 的 1.x 版本线之一。pandas1.5.3最后一批支持 3.7 的 pandas 版本。scipy1.10.11.10 系列仍兼容 3.8 和部分 3.7。matplotlib3.5.33.6 之后基本不再兼容 3.7。requests、certifi这类纯 Python 包相对友好但也尽量别追新。不要在 3.7 环境里硬装新版本依赖那样大概率会引出一堆二进制兼容问题比如某个底层库没有 cp37 的 wheelpip 被迫走源码编译然后编译又报错循环折腾。5.2 系统库与编译链的坑就算把 conda 环境搭好了旧 Python 跑在新版 macOS 上依然有系统层面的兼容性问题。我遇到过的典型情况是两个。第一个是导入某些 C 扩展包时出现Symbol not found或dlopen错误。这是因为 conda 环境里的旧包链接的是旧版libffi、openssl等库而 macOS 新系统带的动态库版本已经变了两者对不上。我的处理方式是在 3.7 环境里显式装兼容的底层库而不是裸依赖系统库CONDA_SUBPOLATFORMosx-64 conda install -n py37 openssl1.1.1 libffi3.3第二个是本地pip install需要编译 C 扩展时新版 clang 对旧代码的警告升级成了错误。这种情况可以试试显式指定 macOS SDK 路径export SDKROOT$(xcrun --show-sdk-path) export CFLAGS-stdliblibc -mmacosx-version-min10.9坦白说这些补丁式的做法不一定对每个人的项目都有效。如果编译一直失败我更推荐考虑切换环境到 Python 3.8 或 3.9 上跑那个项目大概率兼容性更好省下的时间远大于维护 3.7 的成本。5.3 一个务实的项目划分建议经历这一次之后我给自己定了一个规则3.7 环境只用于运行老项目绝不用于开发新功能、绝不用于安装新依赖。原因很简单Python 3.7 生态已经停止增长每装一个新的包你都在和版本墙和档案库缺失作斗争。老项目可以像古董车一样被收藏、偶尔开出去转一圈但你不能指望古董车天天上高速。所以我的目录规划是这样的py37环境只保留老项目本身的依赖全部锁死版本能跑就行py310环境日常开发主力所有新项目都放这里老项目如果未来需要大规模升级依赖优先尝试迁到 Python 3.8 或 3.9而不是往 3.7 里强行塞新组件。这样一来即便 conda 环境出问题你也不会把新项目的进度搭进去。这是一个很务实的环境治理思路和具体报错无关但对长期维护多个项目的 Mac 用户来说真的值得参考。我在 M2 上最终跑通那个老项目的方案是Miniforge 作为 conda 发行版单独建了一个osx-64的 py37 环境把 numpy、pandas、scipy 全部锁定在 3.7 最后支持的版本线上。运行起来很顺唯一代价是每次装包都要记得带CONDA_SUBPOLATFORMosx-64。如果你也卡在PackagesNotFoundError先别急着怀疑网络或卸载 conda。花两分钟跑一下conda search做个体检确认到底是默认源没有 3.7还是arm64 平台没有 3.7再决定走哪条路线。我当初就是没分清这两个原因白白多折腾了一下午。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑