ARTICLE DETAIL

资讯详情

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

macOS下python3安装源全解析:PATH、pip与多版本管理

macOS下python3安装源全解析:PATH、pip与多版本管理 最近又有人在群里问为什么自己刚用brew install python装完python3 -V还是旧的为什么pip3 install装的包换个终端就找不到了为什么 macOS 自带的/usr/bin/python3删不掉、还动不动冒出个externally-managed-environment。这些问题往深了挖本质都是同一个macOS 上的 python3 不是一个而是同时存在好几个安装源彼此井水不犯河水但你一旦搞混 PATH它们就会在你终端里打架。这篇把 macOS 上常见的 python3 安装源逐个讲透系统自带的、Xcode Command Line Tools 的、python.org 官方包的、Homebrew 的、pyenv 的、conda 的、MacPorts 的。它们分别装在哪个目录、版本更新机制是什么、pip 归属谁、删除的风险有多大以及不同场景到底该选哪个。适合刚换了 Mac 准备折腾 Python 环境的新手也适合被 PATH 搞到头大、想一次性理顺的老手。1. 为什么 macOS 上的 python3 不止一个1.1 系统级 python3 到底是谁macOS 从 12.3 开始彻底移除了自带的 python2只留下一个/usr/bin/python3。这个 python3 并不是 Apple 单独维护的项目它和 Xcode Command Line Tools 绑定得很紧。你如果没装过 Command Line Tools第一次在终端里敲git或者python3系统会弹窗让你安装装完之后才会出现/usr/bin/python3。这个系统级 python3 有几个特点需要注意。第一它的版本很保守目前普遍停留在 3.9.x 这个区间。Apple 锁版本不是为了恶心开发者而是因为系统组件里有不少底层脚本依赖它升级 Python 小版本可能把系统组件搞挂。所以它存在的意义首先是供系统内部使用顺带让用户有个兜底 Python 可用。第二它受系统完整性保护SIP约束。你直接用sudo rm /usr/bin/python3之类的方式想去掉它基本不可能也不会成功。因为 macOS 的根目录不是普通用户能随便写的系统组件目录在启动时会被校验。这个设计其实是在保护你别乱动系统 python否则系统里某些服务就罢工了。第三它不是一个完整的 Python 发行版。Apple 裁剪掉了不少东西比如没有完整的 tkinter也没有 IDLE 这种图形化开发工具。你拿它跑普通脚本、做点简单的网络请求没问题但如果要搞图形界面、跑科学计算很容易踩到缺模块的坑。1.2 为什么会有这么多源并行Windows 上的 Python 通常是你手动装的那个.exeLinux 上多数发行版会有一个统一的包管理入口apt、dnf但 macOS 没有一个官方唯一的 Python 分发渠道。苹果不管新版 PythonPyPA 也管不到系统目录于是社区就各自发展出了一套安装方式。Homebrew 会装一个到/opt/homebrew官方 pkg 安装包会把 framework 放到/Library/Frameworkspyenv 会用源码编译出一堆独立版本conda 会在用户目录里再建一个小王国。每个安装源都觉得自己才是默认但操作系统只认 PATH 里排在最前面的那一个。终端里type -a python3列出来一大串乱象就是从这来的。用生活化的方式理解系统自带 python3 是原住民Homebrew 是外来移民conda 是拿了块地搞自治的另一个移民。它们各过各的日子你在终端里敲命令实际上是在问谁站得最靠前谁就回答你。1.3 列一下常见的 python3 候选路径在实际排查问题前先对常见的安装路径有个整体印象这个很重要。下面这些路径在 macOS 上都可能出现且都叫python3/usr/bin/python3 # 系统自带或随 Command Line Tools /Library/Developer/CommandLineTools/usr/bin/python3 # CLT 内置 /opt/homebrew/bin/python3 # Apple Silicon 下 Homebrew /usr/local/bin/python3 # Intel 下 Homebrew 或官方 pkg 的符号链接 /Library/Frameworks/Python.framework/Versions/3.12/bin/python3 # python.org 官方安装包 /opt/local/bin/python3 # MacPorts ~/miniconda3/bin/python3 # Miniconda ~/.pyenv/shims/python3 # pyenv当你发现python3 -V的结果不对时不要直接怀疑是不是系统坏了先跑一下type -a python3看看到底有多少个候选者再对照 PATH 判断谁排第一。这是 macOS Python 环境排障的第一步。2. 主流安装源逐个拆解路径、版本、典型命令2.1 python.org 官方 .pkg 安装包python.org 官方提供的 macOS installer 是可视化.pkg双击安装即可。它会把 Python framework 安装到/Library/Frameworks/Python.framework/Versions/3.x同时在/usr/local/bin下生成python3、pip3等软链接。这个安装源的优势是官方出品版本相对完整带完整标准库、tkinter、IDLE安装方式对非技术用户非常友好而且在 Intel Mac 上与 Homebrew 的/usr/local/bin共存时一般也相安无事。但它的缺点同样明显升级麻烦。官方 pkg 的卸载入口不在系统设置里装新版本时旧版本的 framework 不会自动清理。你装了三四个版本后/Library/Frameworks/Python.framework/Versions/下面会堆着 3.9、3.10、3.11、3.12非常乱。很容易与 Homebrew 的软链接冲突。如果 Homebrew 也在/usr/local/bin里维护了自己的python3软链接谁后装谁覆盖PATH 顺序不同结果就不一样。卸载要手动。官方包里没有提供 uninstall 脚本一般做法是手动删除 framework 目录、/Applications/Python 3.x目录以及/usr/local/bin下相关软链接。操作不难但很多人不知道。如果你只是想在 Mac 上装一个能用、完整、官方的 Python不想理解 Homebrew 和 pyenv 这些概念官方 pkg 确实是可行方案。但如果你后面大概率会碰多个项目、多个版本我的建议是别从它开始。2.2 HomebrewApple Silicon 时代的事实标准Homebrew 在 Apple Silicon Mac 上的安装路径是/opt/homebrewIntel Mac 上是/usr/local。执行brew install python后会把最新稳定版 Python 装到/opt/homebrew/Cellar/python3.x又在/opt/homebrew/bin/python3建一个软链接。brew install python装出来的版本与官方 Release 基本同步更新也比较及时。执行brew upgrade python就能升级干净利落。如果你需要旧版本可以用brew install python3.11这类方式装指定版本但要注意这不会影响当前默认的python3指向除非你显式brew link --overwrite --force python3.11。Homebrew python 自带pip3、venv、ensurepip等基础工具开箱即用。不过新版 Homebrew 的 python 遵循 PEP 668直接全局执行pip3 install requests可能会报externally-managed-environment这是故意的目的是阻止你用 pip 污染 Homebrew 管理的 Python正确做法是先用 venv 建虚拟环境再安装。对于绝大多数开发者来说Homebrew 的 Python 作为日常主力是足够稳的。卸载也方便brew uninstall python。前提是你确认没有其他 Homebrew 包依赖它否则卸载后可能会出现连锁问题。可以用brew uses --installed python查一下依赖关系。2.3 pyenv多版本切换神器但本质也是源码编译安装pyenv 解决的问题很明确一台机器上同时存在好几个 Python 版本项目 A 用 3.9项目 B 用 3.12希望每个项目目录能自动切换到指定版本。brew install pyenv之后用pyenv install 3.12.2拉取、编译、安装一个独立 Python。它并不是下载完整二进制包而是从 python.org 拉源码然后在本地编译所以速度比 brew 慢且依赖系统里有编译工具链和几个关键库。官方文档会建议你先跑一遍brew install openssl readline sqlite3 xz zlib libffi这些是源码编译 Python 时常见的外部依赖。如果缺了后续可能碰到ssl模块不可用、sqlite3模块缺失、readline没生效等怪问题。pyenv 安装完成后会在用户目录~/.pyenv/shims/下生成一系列垫片shim并接管你 shell 里的python3命令。你通过pyenv global 3.12.2或pyenv local 3.11.6切换版本实际上就是在切换shims中去往真实 Python 的链接。pyenv 的缺点也很明显每次安装新版本都要编译一次如果只是需要一个 Python 用那么引入 pyenv 属于过度设计。它的价值在版本切换这个需求出现之后才真正体现出来。2.4 conda/Miniconda科学计算和数据项目的独立王国conda 不是 Python 的普通安装方式它是一个完整的包管理器加环境管理器。通过安装 Miniconda 或 Anaconda 得到conda命令后你可以用conda create -n py312 python3.12创建独立环境环境里的python3指向~/miniconda3/envs/py312/bin/python3。conda 的包来源是 Anaconda 的 channel以及社区维护的 conda-forge很多科学计算包numpy、scipy、pandas、pytorch在 conda 生态里都有预编译的版本。尤其在 Apple Silicon 芯片上有些底层库用 pip 直接装 wheel 没问题但想调试或装带 MPS 支持的版本时conda-forge 往往更省事。但它也有一个坑安装 Miniconda 时初始化脚本会往你的 shell 配置里写入conda init相关代码这意味着每次打开新终端conda 的 base 环境都会被激活python3默认指向 conda 的 base。很多人的为什么我在终端里敲 python3 变成了 conda 的版本就是这么来的。如果你不想让 conda 默认接管终端可以执行conda config --set auto_activate_base false这样新终端就不会自动激活 base只有你执行conda activate 环境名时python3才会指向对应环境的版本。2.5 MacPorts老牌选手但如今确实小众了MacPorts 是 macOS 上历史很悠久的包管理器安装路径在/opt/localport install python312这种方式也可以装 Python。如果你是从 FreeBSD port 时代走过来的老玩家MacPorts 的哲学可能更让你熟悉。但现在已经不太建议新用户从 MacPorts 入手了原因很现实社区活跃度低、软件包更新慢、和 Homebrew 同时存在时容易互相干扰。MacPorts 的路径/opt/local/bin如果排在/opt/homebrew/bin前面会让python3的指向更加混乱。我把几个主流安装源的核心差异整理成了表格方便对比安装源默认安装路径默认版本版本切换卸载难度适合人群系统自带/usr/bin/python33.9.x随系统不支持建议别动应急、只跑简单脚本python.org 官方 pkg/Library/Frameworks/...官方最新稳定版手动手动删除不折腾包管理器的人Homebrew/opt/homebrew/bin最新稳定版brew linkbrew uninstall大多数开发者pyenv~/.pyenv/versions/...用户指定global/local删除目录多版本并行开发者Miniconda~/miniconda3每次创建环境时指定conda activate删除目录数据科学、深度学习MacPorts/opt/local/bin随 ports 更新port selectport uninstall老用户、特殊情况3. PATH 优先级你敲 python3 时系统执行的到底是谁3.1 shell 如何找到 python3终端里输入python3shell 会按照 PATH 变量里列出的目录顺序一个一个去找同名可执行文件。这个顺序就是优先级排在前面的先被命中。比如你的 PATH 是/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin那么系统会先看/opt/homebrew/bin/python3存不存在存在就直接执行它不存在才继续往下找/usr/local/bin/python3。所以哪个安装源成为默认其实不取决于你更喜欢谁只取决于它对应的bin目录在 PATH 里排在第几位。想知道当前全部候选者用type -a python3这个命令会把 PATH 中所有能找到的python3都列出来并标注类型alias、可执行文件等。它能帮你立刻看清到底有几个版本在备选名单里。3.2 zsh 里 PATH 的加载顺序与常见配置位置macOS 默认 shell 从 Catalina 开始是 zsh。zsh 启动时会依次加载这几个文件.zshenv、.zprofile、.zshrc、.zlogin。大多数 Homebrew 安装脚本会把eval $(/opt/homebrew/bin/brew shellenv)写入.zprofile或.zshrcconda 初始化则通常写入.zshrc。如果 Homebrew 和 conda 的 PATH 修改写进了不同的文件加载顺序就会影响谁在 PATH 前面。比如.zprofile里把/opt/homebrew/bin加到了 PATH 最前面.zshrc里 conda init 把~/miniconda3/bin加到了 PATH 最前面由于.zprofile比.zshrc先执行理论上/opt/homebrew/bin会在更前面。但 conda init 往往不是简单地追加路径它会把conda的 base 环境 bin 插入到 PATH 开头。最终结果可能跟你预想的完全不一样。排查这类问题的标准动作先看当前生效的 PATHecho $PATH | tr : \n再对照type -a python3的输出基本就能定位出是谁把python3指向了你不想要的位置。3.3 三个典型灵异事件的排查链路场景一刚用 Homebrew 装完 pythonpython3 -V还是系统老版本大概率是/usr/bin在 PATH 中排到了/opt/homebrew/bin前面或者 shell 配置里根本没有加入 Homebrew 的 bin 目录。解决方式which python3 # 如果输出 /usr/bin/python3说明路径优先级不对把下面这行写进~/.zshrc然后重新打开终端export PATH/opt/homebrew/bin:$PATH场景二python3的版本是对的但pip3装完包后 import 失败这个问题的核心是pip3和python3不一定来自同一个安装源。如果你用/usr/bin/python3 -m pip装包而实际开发时用的是/opt/homebrew/bin/python3那两边自然互不可见。最不容易出错的用法是python3 -m pip install 包名而不是直接pip3 install 包名因为python3 -m pip永远自动绑定当前python3对应的 pip。场景三新开一个终端python3 就变成 conda 的了这通常是 conda init 的默认行为不是故障。执行conda config --set auto_activate_base false新终端就不会自动进入 base 环境了。你需要用某个 conda 环境时手动conda activate 环境名即可。4. 每个 python3 都自带一个 pip3包管理记得对号入座4.1 pip 是绑定解释器的不是全局统一的很多人在 Windows 上习惯装一个 Python然后到处 pip install到了 macOS 上还保持这个习惯于是出了问题pip 装的包代码里 import 失败而且报错信息还特别奇怪。原因很简单macOS 上可能同时存在多个 Python每个 Python 都有自己独立的第三方包目录site-packages。不同安装源的 Python 默认不会共享第三方包你用pip3装包时它属于当时 PATH 里排第一的那个 Python换个终端或者换一种方式调用python3看到的就可能完全是另一个世界。只信任一套组合永远是python3 -m pip install 包名这样无论 PATH 怎样变化至少这回装的包一定进了当前python3能搜到的目录。同理检查包是否装成功用python3 -m pip show 包名4.2 什么是 externally-managed-environment为什么 Homebrew python 会报这个新版本 Homebrew 的 Python 在直接pip3 install某个包时可能会返回一段以error: externally-managed-environment开头的错误提示。这不是 pip 坏了而是 Homebrew 在安装 Python 时写入了 PEP 668 标记告诉 pip这个 Python 由包管理器管理你不要直接往里装全局包。PEP 668 的目的是避免用户用 pip 塞进去的包和 Homebrew 后续升级 Python 时管理的包产生冲突。我在实际工作中见过有人用pip3 install --upgrade pip把系统 Python 的 pip 升到一个不兼容版本导致 Homebrew 的某些依赖 python 的包直接崩溃。这个报错其实是保护机制。如果你确实只想快速装一个开发工具类包可以给当前用户目录建一个虚拟环境python3 -m venv /path/to/venv source /path/to/venv/bin/activate pip install 包名如果只是想用某个命令行工具优先考虑 pipx它会为每个工具创建独立环境省心很多。而强行加--break-system-packages虽然在本地机器上能用但不太推荐作为常规手段因为一旦 Homebrew 升级 Python你全局 pip 包的归属问题会变得更难收拾。4.3 macOS 上全局安装包的稳妥姿势我的建议很朴素**无论你用的是哪个安装源的 python3都别把第三方包直接往全局塞。**官方 pkg 的 python3 没有 PEP 668 的限制全局 pip install 能成功但这只是能成功不代表该这么干。理由在于全局包会带来两个问题版本冲突项目 A 需要 requests 2.28项目 B 需要 requests 2.31全局只能装一个版本。升级后失效Homebrew 或官方 pkg 升级 Python 后全局包可能需要重新编译或重装。Python 3.3 之后标准库自带venv3.12 之后虚拟环境的体验已经非常好每个项目建一个.venv是最省心、最不折腾的方案。平时我基本只往全局装pipx这类工具本身其他都进虚拟环境。5. 按场景选安装源少走弯路的选择建议5.1 日常脚本、小工具、Web 开发Homebrew 优先如果你的需求是本地写点小工具、跑跑脚本、搞搞 Django/FlaskHomebrew 的 python3 是最省事的选择。它的升级路径清晰、社区资料多、出问题好排查。装完后配合 venv 使用基本不会踩到全局环境混乱的坑。有人可能会纠结官方 pkg 和 Homebrew 哪个好。两者都能用但 Homebrew 的卸载更干净、升级更方便。官方 pkg 更接近Windows 上那种傻瓜安装如果你不想接触包管理器也可以选它只是后续升级、卸载要自己注意。5.2 需要同时维护多个 Python 版本的项目pyenv venv比如公司老项目要 Python 3.8新项目要用 3.12科学计算实验又要求 3.10。这时候 pyenv 几乎是必需品。你可以brew install pyenv pyenv install 3.8.18 pyenv install 3.12.2 cd 老项目目录 pyenv local 3.8.18pyenv local会在当前目录生成一个.python-version文件之后进入这个目录python3自动变成 3.8.18离开目录又恢复默认。这种项目级的自动切换Homebrew 和官方 pkg 都做不到。5.3 数据科学、机器学习conda 环境更省心做 pandas、numpy、pytorch 这类科学计算我更建议用 Miniconda 建独立环境。直接conda create -n ml python3.12建一个干干净净的环境再conda install pytorch很多底层依赖 conda-forge 都准备好了不太需要自己面对编译报错。在 Apple Silicon 的 Mac 上用 conda 安装某些带原生扩展的科学计算库通常比 pip 的纯 wheel 方案更省心。当然 pip 现在也能装但 conda 的 channel 机制在解决非 Python 依赖上的优势依然是独一份的。5.4 只是想跑别人写的一段脚本用系统自带的就行如果你只是临时想跑一下网上下载的脚本不想为此搭建环境直接用/usr/bin/python3加上虚拟环境即可。别往系统 Python 里全局装任何东西。如果系统 Python 缺少某些依赖导致脚本跑不起来再去考虑装一个 Homebrew 的 Python。实际上在我的使用经验里平时python3 -V看到的版本是系统自带的 3.9这种情况虽然看起来旧但对运行大多数不涉及新语法特性的脚本并没有影响。真正需要新版本时再进正式开发环境也不迟。6. 可直接照抄的干净配置流程与踩坑记录6.1 我的推荐安装顺序如果你是一台全新的 Mac想一次把 Python 环境理顺我建议按这个顺序操作。第一步安装 Command Line Toolsxcode-select --install这会提供编译工具链和系统级 python3 的依赖基础。第二步安装 Homebrew/bin/bash -c $(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)如果你在国内网络下载不太稳定可以找国内公开镜像加速 Homebrew 安装具体方法在 Homebrew 官方镜像帮助里都有这里不赘述。第三步安装 Homebrew 的 Python 和 pyenvbrew install python pyenv第四步配置 shell。在~/.zshrc中加入export PATH/opt/homebrew/bin:$PATH eval $(pyenv init -)然后执行source ~/.zshrc。第五步用 pyenv 安装你需要的 Python 版本pyenv install 3.12.2 pyenv global 3.12.2最终验证type -a python3 python3 -V正常情况下python3会指向~/.pyenv/shims/python3而pyenv global指定的版本就是 3.12.2。如果你想直接使用 Homebrew 的 python3 而不开 pyenv那就不做第五步并且不要在 shell 里加pyenv init那行即可。6.2 我踩过的四个高频坑第一个坑是安装完 Homebrew 后python3还是老版本。原因通常是 PATH 里/opt/homebrew/bin的位置不对。我后来学乖了每次配置完 PATH 先echo $PATH确认一下别省这一步。第二个坑是直接用pip3 install装包结果装到了另一个 Python 里。现在我已经改掉这个习惯了全用python3 -m pip这句话哪怕在虚拟环境里也适用。第三个坑是升级 macOS 后某些依赖 python 的 Homebrew 包突然不可用。这个多半是因为系统升级后 cmdline tools 路径或版本变了。先跑brew doctor看提示必要时brew reinstall受影响的包别急着重装系统。第四个坑是 conda 的 base 环境默认接管终端。我自己的解决方案是conda config --set auto_activate_base false需要时再手动conda activate这样终端里的python3不会被 conda 绑架日常开发和其他工具也能安心共存。6.3 我的日常使用习惯我现在的工作流大概是这样的系统自带的/usr/bin/python3应急用比如临时跑一段维护脚本。Homebrew python3日常写脚本、做小项目的主力配合 venv 隔离依赖。pyenv当需要在多个版本之间快速切换时用比如复现老项目 bug。Miniconda做数据分析和深度学习实验时单独建环境不跟其他环境混。这个组合看起来装了挺多东西但职责边界很清楚互相不会打架。每次换新电脑我基本都能在半小时内把 Python 环境恢复到顺手的状态。如果你现在正被到底该用哪个 python3困住我的建议很简单先别急着选跑一下type -a python3和echo $PATH看清楚机器上到底有谁、谁排前面。搞清楚这几条你对 macOS 上 Python 环境的掌控度就已经超过大多数人了。
返回列表