我正准备前往 PyCon US,所以又开始涉足 Python 开发。(如果你也要去那里,并且想分享你的 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
执行该命令后,我们的点文件(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 解释器,但不知道如何有效地管理它们。 太多时候,人们只是下载最新的 Python 版本,将其移动到他们的 路径,并将其称为一天的工作(或者使用 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-get 或 yum 的强大功能。 如果您是 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 瓶子,使其指向最新的版本。 由于 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 命令是以前的版本,则必须单独对其进行别名设置。 首先,我们需要检查我们使用的版本
# 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 月发表,并已由编辑更新。
13 条评论