在 Mac 上将 Python 3 设置为默认版本的正确和错误方法

在 macOS 上开始使用 Python 3 有几种方法,但其中一种方法优于其他方法。
844 位读者喜欢这篇文章。
Python programming language logo with question marks

Opensource.com

我正在重新投入 Python 开发,为前往 PyCon US 做准备。(如果您也要去那里并想分享您的 Python 故事,请告诉我!) 当我安装一个模块进行摆弄时,我收到提醒,我需要尽快安装 Python 3。

$ pip install todoist-python 
DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7.

因此,我做了我们任何人都会做的事情,并在 Google 上搜索了更新我的开发环境的指南,该环境运行在 Mac(macOS 操作系统,以前称为 OS X)上。令我惊讶的是,我只找到了一些 StackOverflow 帖子,它们指向了部分解决方案。以下是如何设置您的环境而不破坏 macOS 操作系统中任何内置组件的完整故事。

1. 安装 pyenv

Moshe Zadka 警告说,这样做如果出错可能会导致对正在运行的 Python 的不可靠的理解,这过度依赖于加载别名的 shell。 我知道 Moshe 熟悉 Python,但我不知道的是,他还是 *许多* Python 教程的作者,以及一本即将出版的关于 macOS 上 Python 开发的书。 他帮助 40 位同事在 macOS 系统上安全且一致地开发 Python,遵循一个核心原则

“所有 Python 开发的基本前提是永远不要使用系统 Python。您不*希望* Mac OS X '默认 Python' 是 'python3'。您希望永远不要关心默认 Python。”

我们如何才能不再关心默认值? Moshe 建议使用 **pyenv** 来管理 Python 环境(要深入了解配置 pyenv,请参阅本文)。该工具管理多个 Python 版本,并被描述为“简单、不唐突,并遵循 Unix 单一用途工具的传统,即做好一件事。”

虽然还有其他 安装选项 可用,但开始的最简单方法是使用 Homebrew

$ brew install pyenv 
?  /usr/local/Cellar/pyenv/1.2.10: 634 files, 2.4MB

2. 安装 Python

现在让我们安装最新的 Python 版本(截至本文撰写时为 3.7.3)

$ pyenv install 3.7.3
python-build: use openssl 1.0 from homebrew
python-build: use readline from homebrew
Downloading Python-3.7.3.tar.xz...
-> https://pythonlang.cn/ftp/python/3.7.3/Python-3.7.3.tar.xz
Installing Python-3.7.3...
## further output not included ##

3. 设置您的全局默认值

现在 Python 3 已通过 pyenv 安装,我们希望将其设置为 pyenv 环境的全局默认版本

$ pyenv global 3.7.3
# and verify it worked 
$ pyenv version
3.7.3 (set by /Users/mbbroberg/.pyenv/version)

pyenv 的强大之处在于它对我们的 shell 路径的控制。 为了使其正常工作,我们需要将以下内容添加到我们的配置文件中(我的为 .zshrc,您的可能为 .bash_profile

$ echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n  eval "$(pyenv init -)"\nfi' >> ~/.zshrc

执行该命令后,我们的 dotfile(zsh 的 .zshrc 或 Bash 的 .bash_profile)应包含以下行

if command -v pyenv 1>/dev/null 2>&1; then
  eval "$(pyenv init -)"
fi

现在我们确信我们正在使用 Python 3.7.3,并且 pip 将随之更新,而无需在版本之间进行任何手动别名设置。 按照 Moshe 的建议使用版本管理器 (pyenv) 使我们能够轻松接受未来的升级,而不会对我们在给定时间运行的 Python 感到困惑。

成功

当您熟悉此工作流程时,您可以 使用 pyenv 来管理多个 Python 版本。 对于依赖项管理,使用虚拟环境也至关重要。 我在文章中提到了如何使用内置的 venv 库,Moshe 建议 virtualenvwrapper 用于管理虚拟环境

了解 Python 运行时

现在您已修复了 Python 版本,可以安全地探索为什么这个问题会让这么多人感到困惑。

macOS 附带的 Python 版本已经过时,Python 建议用于开发。 正如 XKCD 所指出的,有时考虑 Python 运行时可能非常具有挑战性。

Python environment webcomic by xkcd

许多用户已经在他们的计算机上安装了数十个 Python 解释器,但不知道如何有效地管理它们。 通常,人们只是下载最新的 Python 版本,将其移动到他们的 path 中,然后就结束了(或者使用 brew install python3,它会做类似的事情)。 这可能会导致以后以令人沮丧的方式中断,并且很难进行故障排除。

不该做什么

关于如何使 Python 3 成为系统上的默认 Python,我的第一个想法是移动旧版本并添加新版本

# what I thought would work 
# first, I'll find my python binary 
$ which python 
/usr/bin/python 
# next, I'll move it to an unused name 
$ sudo mv /usr/bin/python /usr/bin/python2 
# lastly, I'll move the new binary to the previous path 
$ sudo mv $PATHTOBINARY/python3 /usr/bin/python 

该模式遵循 /usr/bin/ 通常在 Python 的主要版本之间所做的事情,但我很快了解到这是错误的举动

$ sudo mv /usr/bin/python /usr/bin/python2 
mv: rename /usr/bin/python to /usr/bin/python2: Operation not permitted 

值得庆幸的是,macOS 保护我免于破坏我不完全理解的东西。 进一步的研究证明,这正是我们不应该做的事情。

另一件不要尝试的事情

现在我们知道不该做什么,让我们看看我们 *可以* 做什么。 当我们考虑 macOS 上应用程序的常见安装模式时,有几个选项。

将 Python 3 用作 macOS 默认值

Python 的网站有一个 macOS Python 3 安装程序,我们可以下载并使用。 如果我们使用软件包安装,则 /usr/local/bin/ 中将提供一个 python3 文件。

由于无法更改存储在 /usr/bin/ 中的 Python 二进制文件,因此必须使用别名。 别名很棒的地方在于,它特定于我们的命令行 shell。 由于我默认使用 zsh,因此我将以下内容放入 .zshrc 文件中

$ echo "alias python=/usr/local/bin/python3.7" >> ~/.zshrc 

如果您使用的是默认的 Bash shell,则可以将相同的文本附加到您的 .bashrc

$ echo "alias python=/usr/local/bin/python3.7" >> ~/.bashrc 

这种策略有效,但对于未来更新 Python 来说并不理想。 这意味着我们必须记住检查网站并下载新文件,因为 Python 不包含更新的命令行方式。

让 Homebrew 管理 Python 3

Homebrew 项目为 macOS 提供了一个免费且开源的软件包管理器,许多人都依赖它。 它为 Apple 用户提供了类似于 apt-getyum 的功能。 如果您是 Homebrew 用户,您可能已经安装了 Python。 要快速检查,请运行

$ brew list | grep python 
python 

如果在命令下显示 Python,则表示已安装。 它是什么版本? 让我们检查一下

$ brew info python 
python: stable 3.7.3 (bottled), HEAD 
Interpreted, interactive, object-oriented programming language 
https://pythonlang.cn/ 
/usr/local/Cellar/python/3.7.2_1 (8,437 files, 118MB) * 
## further output not included ##

好的,太好了! Homebrew 维护者已更新默认的 Python bottle 以指向最新版本。 由于 Homebrew 维护者比我们大多数人更可靠地更新版本,因此我们可以使用以下命令使用 Homebrew 版本的 Python 3

$ brew update && brew upgrade python 

现在我们要将我们的别名(来自上面)指向 Homebrew 管理的 Python 副本

# If you added the previous alias, use a text editor to update the line to the following 
alias python=/usr/local/bin/python3 

为了确保上面的路径指向 Homebrew 在我们的环境中安装 Python 的位置,我们可以运行 brew info python 并查找路径信息。

这种使用 Homebrew 管理我们的 Python 环境的方法是一个不错的起点,当时对我来说很有意义。

如果我们仍然需要 Python 2 怎么办?

对于任何 Python 新手来说,从 Python 3 开始都很有意义。但是那些仍然需要 Python 2 的人(例如,为了贡献一个仅在 Python 2 中可用的 Python 项目)可以继续使用 /usr/bin/python 中提供的默认 macOS Python 二进制文件

$ /usr/bin/python 
>>> print("This runtime still works!") 
This runtime still works! 

Homebrew 非常棒,它甚至为 Python 2 提供了不同的公式

# If you need Homebrew's Python 2.7 run 
$ brew install python@2 

我们可以随时从 shell 的配置文件中删除别名,以返回到使用系统上默认的 Python 副本。

不要忘记将 pip 更新到 pip3!

pip 命令是专门用于 Python 软件包的默认软件包管理器。 虽然我们已将默认 Python 命令更改为版本 3,但如果 pip 命令是之前的版本,我们必须单独设置 pip 命令的别名。 首先,我们需要检查我们使用的版本

# Note that this is a capital V (not lowercase) 
$ pip -V 
pip 19.0.3 from /Library/Python/2.7/site-packages/pip-19.0.3-py2.7.egg/pip (python 2.7)

为了确保我们安装的软件包与我们的新 Python 版本兼容,我们将使用另一个别名指向兼容版本的 pip。 由于在这种情况下我们使用 Homebrew 作为我们的软件包管理器,因此我们知道它在安装 Python 3 时安装了 pip3。默认路径应与 Python 3 相同,但我们可以通过要求 shell 找到它来确认这一点

$ which pip3 
/usr/local/bin/pip3 

现在我们知道了位置,我们将像以前一样将其添加到我们的 shell 配置文件中

$ echo "alias pip=/usr/local/bin/pip3" >> ~/.zshrc  
# or for Bash 
$ echo "alias pip=/usr/local/bin/pip3" >> ~/.bashrc

最后,我们可以通过打开一个新 shell 或重置我们当前的 shell 并查看我们指向的内容来确认运行 pip 是否指向 pip3

# This command reloads the current shell without exiting the session 
# Alternatively, exit the shell and start a new one
$ exec $0
# Now we can look to see where pip points us 
$ which pip 
pip: aliased to /usr/local/bin/pip3

我们可以避免使用 Homebrew 更新 pip,但这需要 Python 文档中一个更长的教程

从一开始就做对

如果您刚开始在 macOS 上进行 Python 开发,请进行必要的配置以确保从一开始就使用正确的 Python 版本。 安装 Python 3(无论是否使用 Homebrew)并使用别名可以让你开始编码,但从长远来看,这不是一个好的策略。 使用 pyenv 作为一个简单的版本管理解决方案,让你有一个好的开端。


本文最初发表于 2019 年 5 月,并已由编辑更新。

标签
I'm happiest at a microphone
Matt 曾是一位 EMC 存储专家、VMware vExpert,并且是其他专有技术的粉丝。 他现在专注于开源和 DevRel 采用。
Moshe sitting down, head slightly to the side. His t-shirt has Guardians of the Galaxy silhoutes against a background of sound visualization bars.
自 1998 年以来,Moshe 一直参与 Linux 社区,帮助举办 Linux“安装聚会”。 自 1999 年以来,他一直在编程 Python,并为核心 Python 解释器做出了贡献。 自这些术语存在之前,Moshe 一直是 DevOps/SRE,他非常关心软件可靠性、构建可重现性和其他此类事情。

贡献者

13 条评论

很棒的文章。感谢分享。

立刻遇到了 zlib 的问题。对于遇到同样问题的任何人,您可以在 pyenv 的 github issues 页面找到解决方案。问题编号 1219

只想说声谢谢您的教程。我才刚开始接触 Python 编程,想一开始就走上正确的道路!

感谢您花时间写这个教程。我只想补充一点,看看是否有人遇到这个小问题。就在 "exec $SHELL" 之前,我必须完全退出 iTerm2 才能显示 3.7.4 的报告。我想我可以尝试 source ~/.zshrc。我没试过。

感谢您告知我 Jay。我相信 exec 应该足以在当前会话中实例化一个新的 shell,但 source 肯定会重新加载文件中的信息。

回复 Jay (未验证)

我现在明白哪里出错了。`$SHELL` 被设置为默认 shell,这可能不是您当前正在使用的 shell。我已经将其调整为 `exec $0`,以便 $0 检测当前 shell,而不是默认 shell。再次感谢 Jay 指出这一点!

回复 mbbroberg

如果我在脚本中加入 #!/usr/bin/python,会使用 pyenv 管理的 python 3.7 吗?
会被使用吗?

非常好的工作,非常感谢

Moshe 说得对。请永远不要使用系统 Python 进行开发。即使使用虚拟环境也不行。您需要能够随意切换版本。

使用 "python -m pip" 而不是运行 "pip" 或 "pip3" - 这样 pip 和 python 版本始终匹配,无论您当前选择哪个作为 "python"。

我还建议您看看 Conda - 它对不熟悉系统管理的人特别有用。

使用 pyenv 控制 shell 路径时,eval 关键字前面有多余的空格。请务必删除它,否则您将看到“eval command not found”。确保您也将输出附加到正确的 rc 文件 :).

我按照提到的所有步骤操作,并且它们都显示 python 3.7,但最后当我执行 python -V 时,它仍然显示版本为 2.7。 有什么办法可以覆盖 python 版本吗?

嘿 Saurav! 当您运行 `which python` 时,它显示一个 shim 路径还是一个直接到 /usr/bin/python 的路径? 如果是后者,请确保您的 .bashrc 或 .zshrc (取决于您的 shell) 中有 `eval "$(pyenv init -)"` 语句。

回复 Saurav Ganguli (未验证)

Creative Commons License本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
© . All rights reserved.