1. 项目概述为什么在Apple Silicon上装Python 3.6是个“技术活”如果你手头有一台搭载M1、M2或M3芯片的MacBook想在上面跑一个老项目而项目依赖明确要求Python 3.6那你大概率会碰壁。这可不是简单的“下载-安装”就能搞定的事。作为从Intel时代一路用过来的开发者我深刻体会到从x86架构切换到Apple SiliconARM架构不仅仅是性能的提升更意味着整个软件生态的底层基础发生了改变。Python 3.6的官方支持已于2021年底结束其预编译的安装包比如通过官网下载的pkg安装程序绝大多数是针对Intelx86_64架构的。直接在ARM架构的Mac上运行要么直接报错要么通过Rosetta 2转译为后续的包安装埋下兼容性“地雷”。所以这个“安装”动作本质上是在一个新时代的硬件上复活一个旧时代的软件环境。核心矛盾在于ARM原生兼容性、已终止的官方支持、以及现代包管理工具如pip对老版本Python日益减少的支持。本文将带你彻底拆解在M系列芯片Mac上部署Python 3.6的几种主流方案从最省事的“一键”方案到最底层的“从源码编译”我会结合自己的踩坑经验详细说明每一步的操作意图、潜在风险以及如何选择最适合你的那条路。无论你是为了维护遗留系统还是学习需要这篇指南都能让你少走弯路。2. 核心思路与方案选型四条路径的深度剖析面对这个问题我们通常有四条路径可走。选择哪一条取决于你的具体需求、技术偏好以及对“干净”程度的容忍度。下面这张表格清晰地对比了它们的核心区别方案核心原理优点缺点适用场景1. 使用pyenv管理通过源码编译或安装预编译的二进制包在用户目录下管理多个独立的Python版本。高度推荐。版本隔离彻底不影响系统Python可通过补丁解决编译问题社区支持好。首次编译可能耗时较长10-30分钟需要解决一些依赖问题。绝大多数开发场景尤其是需要多个Python版本共存时。2. 使用conda如Miniforge使用为ARM架构预编译好的Python 3.6及其科学计算包。开箱即用无需编译强大的环境与包管理能力特别适合数据科学领域。环境相对较重包生态以数据科学为主某些纯Python的PyPI包可能仍需从源码构建。数据科学、机器学习项目且项目依赖numpy,pandas等科学计算库。3. 使用Docker容器在容器内运行一个完整的、基于Intel架构的Linux系统及Python 3.6环境。环境隔离性最强与宿主机Mac的架构完全解耦保证环境一致性。需要安装Docker Desktop占用磁盘和内存性能有轻微损耗文件共享需要额外配置。需要绝对的环境复现性或项目本身就在Linux容器中运行。4. 从源码手动编译下载Python 3.6源码在本地配置、编译、安装。最灵活、最底层的控制适合学习和深度定制。步骤最繁琐对新手不友好需要自行解决所有依赖和编译错误。学习Python构建过程或需要对解释器进行特殊修改的场景。我的选择建议对于绝大多数开发者首选方案是pyenv。它完美解决了版本隔离和ARM原生编译的问题是Python社区公认的标准多版本管理工具。如果你的项目重度依赖numpy、scikit-learn等且你不想在编译这些C扩展上浪费时间那么**condaMiniforge** 是更优选择。Docker方案则像是一个“保险箱”当你需要确保环境百分百一致或者项目复杂到本地难以调试时它是终极武器。手动编译更多是教育意义日常开发不推荐。接下来我将重点详解最实用的pyenv和conda方案并简要说明Docker方案的要点。3. 方案一详解使用pyenv安装与管理Python 3.6pyenv的工作原理是在你的用户主目录下例如~/.pyenv维护多个独立的Python版本。当你切换版本时它只是改变PATH环境变量的指向非常轻量和高效。3.1 环境准备与pyenv安装首先我们需要安装pyenv本身。在Apple Silicon Mac上推荐使用Homebrew来安装这是最简洁的方式。安装Homebrew如果尚未安装 打开终端Terminal粘贴以下命令。注意此命令会要求你安装Xcode Command Line Tools按提示确认即可。/bin/bash -c $(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)安装完成后根据终端输出的提示将Homebrew的可执行文件路径添加到你的shell配置文件如~/.zshrc中。通常命令类似echo eval $(/opt/homebrew/bin/brew shellenv) ~/.zshrc source ~/.zshrc通过Homebrew安装pyenvbrew install pyenv配置Shell以启用pyenv 同样需要将pyenv的初始化脚本添加到你的shell配置文件中。编辑~/.zshrc文件如果你使用bash则是~/.bash_profile或~/.bashrcecho export PYENV_ROOT$HOME/.pyenv ~/.zshrc echo command -v pyenv /dev/null || export PATH$PYENV_ROOT/bin:$PATH ~/.zshrc echo eval $(pyenv init -) ~/.zshrc然后让配置生效source ~/.zshrc现在运行pyenv --version应该能正确显示版本号。注意Apple Silicon Mac的Homebrew默认安装在/opt/homebrew目录下这与Intel Mac的/usr/local不同。上述路径配置都是针对ARM架构的。如果你之前从Intel Mac迁移过来有旧的Homebrew在/usr/local建议进行清理避免冲突。3.2 安装Python 3.6.15及解决编译问题pyenv安装Python有两种方式下载预编译的二进制包更快或从源码编译。对于已终止支持的Python 3.6官方很少提供ARM原生预编译包所以我们通常需要编译。查看可安装的版本pyenv install --list | grep 3.6你会看到一系列3.6.x的版本建议选择该分支的最终版本3.6.15它包含了该系列的所有安全更新。尝试直接安装很可能会失败pyenv install 3.6.15在M系列芯片上直接编译大概率会失败错误信息通常与_ctypes模块或SSLOpenSSL有关因为Python 3.6自带的某些配置或依赖版本较旧与macOS新系统不兼容。解决编译依赖问题 我们需要通过Homebrew安装一些必要的依赖库特别是新版OpenSSL。brew install openssl readline sqlite3 xz zlib tcl-tk关键步骤在安装Python时我们需要告诉编译器这些库的位置。pyenv提供了一个非常方便的功能在安装命令前设置环境变量。CFLAGS-I$(brew --prefix openssl)/include -I$(brew --prefix readline)/include -I$(brew --prefix sqlite3)/include -I$(brew --prefix xz)/include -I$(brew --prefix zlib)/include -I$(brew --prefix tcl-tk)/include LDFLAGS-L$(brew --prefix openssl)/lib -L$(brew --prefix readline)/lib -L$(brew --prefix sqlite3)/lib -L$(brew --prefix xz)/lib -L$(brew --prefix zlib)/lib -L$(brew --prefix tcl-tk)/lib pyenv install 3.6.15这个命令做了两件事CFLAGS指定了头文件的查找路径LDFLAGS指定了库文件的链接路径。$(brew --prefix openssl)会自动替换为Homebrew安装openssl的实际路径如/opt/homebrew/opt/openssl3。针对_ctypes模块的特殊处理 即使配置了上述路径在macOS Monterey及更高版本上编译_ctypes模块可能仍会失败报错提及libffi。这是因为Python 3.6的构建系统查找libffi的方式有问题。我们需要额外指定libffi的路径它通常随Xcode Command Line Tools或Homebrew的某些包安装。 一个更稳健的方法是使用pyenv社区维护的一个补丁。但更简单直接的方法是在安装命令中显式传递LIBFFI的路径。首先确认libffi是否存在find /opt/homebrew -name libffi.* 2/dev/null | head -5如果找到例如在/opt/homebrew/opt/libffi/lib则在安装命令中加入CFLAGS-I$(brew --prefix openssl)/include -I$(brew --prefix readline)/include -I$(brew --prefix sqlite3)/include -I$(brew --prefix xz)/include -I$(brew --prefix zlib)/include -I$(brew --prefix tcl-tk)/include LDFLAGS-L$(brew --prefix openssl)/lib -L$(brew --prefix readline)/lib -L$(brew --prefix sqlite3)/lib -L$(brew --prefix xz)/lib -L$(brew --prefix zlib)/lib -L$(brew --prefix tcl-tk)/lib -L/opt/homebrew/opt/libffi/lib CPPFLAGS-I/opt/homebrew/opt/libffi/include pyenv install 3.6.15增加了CPPFLAGS和LDFLAGS中libffi的路径。实操心得编译过程可能会持续10到30分钟取决于你的机器性能。如果中途失败仔细阅读错误日志的最后几行通常是某个依赖没找到。核心思路就是缺什么就用brew install装什么然后在CFLAGS和LDFLAGS里加上它的路径。成功编译后pyenv会自动将该版本安装到~/.pyenv/versions/3.6.15目录下。3.3 版本切换与虚拟环境管理安装成功后你可以管理这个版本了。查看已安装版本pyenv versions带星号(*)的是当前全局激活的版本通常是系统自带的Python。设置全局或本地版本全局设置影响整个系统pyenv global 3.6.15本地设置仅影响当前目录及其子目录pyenv local 3.6.15。这会在当前目录创建一个.python-version文件。 我强烈建议不要将Python 3.6设置为全局版本以免影响其他新项目。使用pyenv local为特定项目目录指定版本是最佳实践。创建虚拟环境 即使为项目指定了Python 3.6也强烈建议在项目内使用虚拟环境来隔离包依赖。pyenv提供了一个好用的插件pyenv-virtualenv。brew install pyenv-virtualenv同样将初始化命令添加到~/.zshrcecho eval $(pyenv virtualenv-init -) ~/.zshrc source ~/.zshrc现在你可以基于Python 3.6.15创建一个虚拟环境pyenv virtualenv 3.6.15 my-project-env然后进入你的项目目录激活这个环境cd /path/to/your/project pyenv local my-project-env # 让该目录自动使用此虚拟环境激活后你的命令行提示符前通常会显示虚拟环境名(my-project-env)。之后所有pip install操作都只影响这个环境。4. 方案二详解使用CondaMiniforge获取预编译环境如果你的项目是数据科学相关的或者你不想折腾编译那么Conda是更好的选择。但注意官方的Anaconda对ARMM系列芯片的官方支持起步较晚且体积庞大。这里我们使用Miniforge它是一个轻量级的、社区驱动的Conda发行版专门为ARM64架构包括Apple Silicon提供预编译的包。4.1 安装Miniforge下载安装脚本 访问 Miniforge 的 GitHub Release 页面找到适用于 macOS ARM64 的最新安装脚本。或者直接在终端使用curl下载curl -L -O https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-MacOSX-arm64.sh运行安装脚本bash Miniforge3-MacOSX-arm64.sh按照提示进行安装。建议安装到默认位置~/miniforge3并选择“yes”让安装程序初始化你的shell通常是~/.zshrc。激活Conda 关闭并重新打开终端或者运行source ~/.zshrc现在你的命令行提示符前应该出现了(base)表示你处于Conda的base环境中。4.2 创建Python 3.6的Conda环境Conda的强大之处在于它把Python解释器和包一起作为一个可管理的“环境”。创建新环境conda create -n py36_env python3.6这里的-n py36_env指定了环境名python3.6指定了Python版本。Conda会自动解析并安装适用于ARM64架构的Python 3.6.x最新兼容版本可能是3.6.15及其核心依赖。激活环境conda activate py36_env提示符会变为(py36_env)。安装包 你可以使用conda install来安装包Conda会优先从conda-forge频道寻找预编译好的ARM64版本这能最大程度避免编译问题。例如conda install numpy pandas scikit-learn如果某个包在Conda频道中没有你仍然可以使用pip install但要注意此时pip安装的包如果需要编译C扩展可能会遇到与之前pyenv编译Python时类似的架构问题。不过许多纯Python包没有问题。注意事项Conda环境是自包含的与系统的pyenv或其他Python安装互不干扰。当你不需要时可以conda deactivate退出或者用conda remove -n py36_env --all删除整个环境。5. 方案三简述使用Docker实现跨架构隔离Docker的思路是“打不过就加入”——既然在macOS ARM上原生运行x86的Python 3.6有困难那我直接跑一个x86的Linux容器好了。所有的兼容性问题都被封装在容器内。安装Docker Desktop for Mac从Docker官网下载并安装Apple Silicon版本。拉取Python 3.6镜像例如官方镜像python:3.6-slim。docker pull python:3.6-slim这个镜像是基于Linux x86_64的Docker Desktop会在M系列芯片上自动通过Rosetta 2的二进制转译来运行它对用户透明。运行容器并开发docker run -it --rm -v $(pwd):/workspace -w /workspace python:3.6-slim bash这个命令做了几件事-it启动交互终端--rm退出后自动删除容器-v将当前目录挂载到容器的/workspace-w设置工作目录。进入容器后你就拥有了一个纯净的Python 3.6 Linux环境。在容器内操作你可以在容器内使用pip install安装依赖运行你的脚本。所有改动如果保存在挂载的目录/workspace下在宿主机你的Mac上也能看到。优点环境绝对一致与宿主机完全隔离。缺点需要学习基本的Docker命令文件编辑和调试不如本地环境直观性能有微小损耗。适合作为持续集成CI或复杂部署环境的本地复现手段。6. 常见问题与排查技巧实录在实际操作中你可能会遇到以下问题。这里记录了我的排查思路和解决方法。6.1pyenv编译失败报错ModuleNotFoundError: No module named _ctypes这是最常见的问题。根本原因是Python的ctypes模块依赖的libffi库在编译时没有被正确链接。排查在编译输出的日志中搜索_ctypes相关的错误。通常会在building _ctypes extension阶段失败。解决确保已通过Homebrew安装了libffibrew install libffi在安装Python时显式传递libffi的头文件和库路径正如3.2节第4步所示。关键是CPPFLAGS和LDFLAGS。如果还不行可以尝试在安装前导出这些变量export LDFLAGS-L/opt/homebrew/opt/libffi/lib export CPPFLAGS-I/opt/homebrew/opt/libffi/include然后再运行pyenv install命令。6.2 使用pip安装包时报错关于arm64或x86_64架构不兼容这通常发生在你用pyenv方案安装的Python 3.6环境中尝试安装带有C扩展的第三方包如cryptography、psycopg2等。这些包的老版本可能没有提供ARM64的预编译轮子wheelpip会尝试从源码编译而编译环境可能缺少依赖。排查错误信息中常包含error: command /usr/bin/clang failed with exit code 1并伴随大量编译器输出。解决升级pip和setuptools老版本的pip可能无法正确识别平台。pip install --upgrade pip setuptools wheel寻找替代包或更新版本有些包的新版本已支持ARM64。如果项目允许尝试升级包版本。使用Conda如果这个包在数据科学领域常用如numpy考虑切换到Conda环境它提供了预编译的ARM64版本。手动安装系统依赖根据错误提示用Homebrew安装缺失的系统库。例如psycopg2需要libpq可以brew install postgresql。6.3 使用Conda安装某些包时速度慢或失败Conda默认的频道可能在某些地区访问较慢或者没有某个包。排查conda install长时间卡在Solving environment或下载失败。解决添加国内镜像源如清华源这能极大提升下载速度。可以配置.condarc文件。指定conda-forge频道conda-forge社区频道包更全。安装时使用conda install -c conda-forge package_name。使用mambamamba是一个用C重写的Conda包管理器速度更快。可以用conda install -c conda-forge mamba安装然后用mamba install代替conda install。6.4 如何确认Python正在以原生ARM模式运行在终端里激活你的Python 3.6环境然后运行import platform print(platform.machine())如果输出的是arm64恭喜你这是原生模式。如果输出x86_64说明它正在通过Rosetta 2转译运行这可能发生在你错误地安装了Intel版本的Python或者在某些容器环境下。原生模式的性能更好兼容性也更佳。6.5 项目依赖文件requirements.txt中的包安装失败老项目的requirements.txt可能包含已经过时或不兼容的包版本。策略不要一次性安装所有包。先安装核心的、版本要求不严格的包。对于每个安装失败的包尝试不指定版本安装让其安装最新兼容版pip install package_name搜索该包在PyPI上的历史版本尝试稍新但仍兼容的版本。如果包已彻底废弃寻找其替代品或Fork版本。 这是一个需要耐心和试错的过程也是维护老项目不可避免的挑战。最后我的个人体会是在Apple Silicon上维护老版本Python项目pyenv配合细致的依赖管理是平衡灵活性和控制力的最佳选择。而CondaMiniforge则是数据科学家的“救星”它能让你几乎免于编译之苦。把这两种工具玩熟再加上Docker作为终极隔离手段你就能在M系列芯片的Mac上从容应对绝大多数历史遗留的Python环境问题了。记住关键不是记住所有命令而是理解每种方案背后的原理架构隔离、包管理和环境虚拟化。这样无论遇到什么新问题你都能自己找到解决路径。