核心要点:
- 修复 externally-managed-environment 错误最稳妥的方法,是为每个项目创建单独的虚拟环境
- 对于属于操作系统的 Python 包,应使用 apt、dnf 或其他系统包管理器进行安装
- 对于希望在终端中直接使用的 Python 命令行应用,应使用 pipx 进行安装
您之所以看到 externally-managed-environment 错误,是因为 pip 正尝试向操作系统所管理的 Python 环境中安装软件包。该限制的存在,是为了防止 pip 修改系统包并引发依赖冲突。多数情况下,最佳做法是改为在虚拟环境中安装该软件包。
请继续阅读,了解该错误产生的原因及解决方法。
Externally-Managed-Environment 错误:含义与成因
externally managed environment(外部管理环境)指的是由操作系统包管理器或其他外部包管理器(而非 pip)控制的 Python 安装环境。
具体来说,Linux 发行版预装 Python,是因为操作系统自带的部分软件和系统工具使用 Python 编写,或依赖 Python 库。
因此,您的操作系统可能已经预装了 Python 及系统包。当 pip 尝试向该 Python 环境安装软件包时,会检测名为 EXTERNALLY-MANAGED 的文件,并阻止安装操作。
这一点很重要,因为如果不这样做,pip 可能会修改系统中其他软件所依赖的包。
例如,Ubuntu 的 add-apt-repository 命令依赖 Python 以及由系统管理的 Python 包。如果 pip 将其中某个依赖替换为不兼容的版本,该命令可能无法正常运行。
这正是 externally-managed-environment 机制所要防止的问题。
Python 环境管理的最佳实践
Python 环境管理的最佳实践,归根结底是让每个 Python 包都由对应的包管理器来控制。
如果 Ubuntu 系统本身需要某个 Python 包,应由系统包管理器管理;如果是您自己的 Python 项目需要某个包,则应将其放入虚拟环境中。
这样做可以帮助您避免两类问题:
- 归属冲突,指两个包管理器都认为自己负责同一个包
- 依赖冲突,指两个程序需要同一个包的不兼容版本
以下是几条让 Python 环境保持整洁、互不干扰的建议:
- 为每个 Python 项目使用独立的虚拟环境,例如我们关于 Python 网络爬取的指南展示了如何创建环境并添加爬虫所需的库
- 在使用 pip 安装软件包之前,请先激活虚拟环境
- 如果想确保 pip 与您正在使用的解释器保持关联,可以使用 python -m pip
- 将项目依赖记录在 requirements.txt 或 pyproject.toml 等文件中
- 对于属于操作系统的软件包,应使用 apt、dnf 或您所用 Linux 发行版自带的包管理器
将系统包与项目依赖分开管理,能让您更清楚地了解 Python 环境中每个部分由哪个包管理器控制。对于需要发送大量请求的项目,可以通过住宅代理来转发这些请求。
轮换住宅 IP 可以定位到特定地区,并降低因请求过多而导致单个 IP 被限速的概率。
如何修复 Python 中的 externally-managed-environment 错误
正确的修复方法取决于您要安装的内容,以及它属于您自己的 Python 项目还是操作系统。
使用虚拟环境(推荐方案)
如果该软件包用于您自己的 Python 项目,请创建虚拟环境并在其中安装,而不要修改系统 Python 环境。
第一步:打开终端
在 Ubuntu 及许多其他 Linux 桌面环境中,按 Ctrl + Alt + T 即可打开终端。
第二步:检查 Python 3 是否已安装
执行:
python3 --version
如果已安装 Python 3,终端应返回类似以下的版本号:
Python 3.12.3
您看到的版本号可能有所不同,只要以 Python 3 开头即可。如果不是,请下载并安装 Python。
第三步:进入您正在处理的项目目录
假设您的项目保存在名为 python-project 的目录中,请执行:
cd python-project
这会将终端切换到该项目目录中。
第四步:创建虚拟环境
执行:
python3 -m venv .venv
执行该命令后会发生以下情况:
- python3 运行您的 Python 3 解释器
- -m venv 运行Python 的 venv 模块,用于创建虚拟环境
- .venv 是 Python 将创建新虚拟环境的目录名称
第五步:激活虚拟环境
执行:
source .venv/bin/activate
此后,当前终端会话中的 Python 解释器和 pip 都将指向 .venv。
此时,您会看到命令提示符的开头出现 (.venv)。
第六步:确认当前使用的是虚拟环境
执行:
command -v python
如果一切正常,终端应显示指向您刚创建的虚拟环境的路径,例如:
/home/you/python-project/.venv/bin/python
这说明当前终端使用的是 .venv 内的 Python 解释器,而非系统 Python。
第七步:安装您最初想要安装的软件包
现在您应该可以安装之前引发 externally-managed-environment 错误的软件包了,例如:
python -m pip install requests
在上面的示例中,Python 会将 Requests 库安装到您刚创建的环境中。关于如何选择合适的库,请参阅我们的HTTPX vs Requests vs AIOHTTP 指南。
无论哪种情况,像这样的虚拟环境都能让项目依赖与系统包保持分离。这样一来,您可以轻松修改项目所需的包,而不会影响操作系统所管理的 Python 安装。
使用系统包管理器(备选方案)
如果您要使用的软件包属于操作系统而非您自己的 Python 项目,可以使用系统包管理器进行安装。这样该包就由操作系统控制,而不是由 pip 管理。
在 Ubuntu 或 Debian 上使用 apt,在 Fedora 上使用 dnf。
本例以 python3-apt 为例。该软件包为 Python 提供了访问 Ubuntu 和 Debian 所用 APT 包管理库的能力。由于它属于系统包管理体系,应使用 apt 进行安装和管理。
具体操作如下:
第一步:打开终端
按 Ctrl + Alt + T 打开终端。
第二步:检查该软件包是否可用
执行:
apt show python3-apt
这可以确认 python3-apt 是否可以通过您计算机上配置的软件源获取。
第三步:更新 APT 的软件包列表
执行以下命令:
sudo apt update
以刷新 APT 对已配置软件源中可用软件包的信息。
第四步:安装 python3-apt
执行:
sudo apt install python3-apt
APT 会告知您将要安装或更改的内容,并可能要求您确认。如果 python3-apt 已经安装,APT 则会直接告知您这一情况。
第五步:确认该软件包可以正常使用
执行:
python3 -c "import apt; print(apt.__file__)"
如果一切正常,Python 会显示已安装 apt 模块的位置。如果出现导入错误,说明系统 Python 解释器无法访问该模块。
使用 pipx 安装应用
pipx 是一种用于在隔离环境中安装 Python 命令行应用的工具,它会为每个安装的应用自动创建一个虚拟环境。
假设您想安装 HTTPie 这类 Python 应用,并直接在终端中使用。这时 pipx 就很实用,它会专门为 HTTPie 创建虚拟环境,使其依赖与系统 Python 保持分离。
该应用不依附于任何特定项目,因此您可以在终端的任意位置运行它。
请按照以下步骤,在您的 Ubuntu 电脑上安装 pipx:
第一步:打开终端
按 Ctrl + Alt + T 打开终端。
第二步:更新 APT 的软件包列表
然后输入以下命令:
sudo apt update
这会刷新 Ubuntu 中已配置软件源的可用软件包列表。
第三步:安装 pipx
执行:
sudo apt install pipx
这会通过系统包管理器安装 pipx。
第四步:将 pipx 应用添加到 PATH
执行:
pipx ensurepath
这可以确保 pipx 存放已安装应用的目录被包含在 PATH 中。
第五步:确认 pipx 已安装
执行:
pipx --version
如果看到版本号,说明 pipx 已安装并可以正常使用。
第六步:安装 Python 命令行应用
现在您可以使用以下命令安装 HTTPie 等命令行应用:
pipx install httpie
安装完成后,您无需先激活其虚拟环境,即可在终端中直接运行 http 命令。如果想确认 pipx 正在管理哪些应用,只需执行:
pipx list
为什么正确管理 Python 环境很重要
如果将 Python 包安装到错误的环境中,或让不相关的软件共用同一个 Python 环境,可能面临以下风险:
pip 安装可能导致系统工具无法正常运行
假设 Ubuntu 中安装了:
System Python
└── Package A 1.4,
并且 Ubuntu 的某个工具依赖该软件包。此时如果您针对系统 Python 执行 pip,并将其替换为 Package A 2.0。
此时,该系统工具可能因遇到不兼容的版本而无法正常运行。这也是为什么属于您自己项目的软件包,最好安装在虚拟环境中,而不是安装到系统 Python 中。
并且 Ubuntu 的某个工具依赖该软件包。此时如果您针对系统 Python 执行 pip,并将其替换为 Package A 2.0。
此时,系统工具可能会因为遇到并非为其打包的版本而无法正常工作。因此,属于您自己项目的包最好安装在虚拟环境中,而不是直接安装到系统 Python 里。
一个 Python 项目可能影响另一个项目
假设您有两个 Python 项目:一个使用 Django 4.2,另一个需要 Django 5.2。如果两个项目使用同一个 Python 环境,为第二个项目安装 Django 5.2 可能会替换掉第一个项目所依赖的版本。
更安全的做法是为每个项目创建各自独立的虚拟环境,这样一个项目使用 Django 4.2 时,就不会受到为其他项目安装的版本影响。
您可以在我们的Python Google Trends 爬虫项目中看到这种做法的实际应用:在构建爬虫之前,我们先在虚拟环境中安装项目所需的库。
您的项目可能在一台机器上正常运行,却在另一台机器上报错
如果您一直将项目的包安装在全局环境中,项目可能仅仅因为您的电脑上已经装了这些包而正常运行。一旦将同一个项目迁移到另一台机器上,就可能因为那台机器没有安装相同的包而运行失败。
为每个项目创建虚拟环境有助于避免这个问题。您还应该将项目的依赖记录在 requirements.txt 或 pyproject.toml 等文件中,这样在另一台机器上配置项目时,就能在相同的环境中安装所需的包。
让 Python 环境的每个部分都安装在各自对应的环境中,可以降低某处的包变动影响到其他地方软件的风险。如果您仍然遇到报错,可以参考我们的Python 解析错误修复指南,其中介绍了常见的语法问题及其解决方法。
总结
事情就是这样:终端之所以显示 externally-managed-environment 错误,是因为 pip 尝试安装或修改一个由操作系统包管理器控制的 Python 环境。这项限制有助于防止依赖冲突,并阻止 pip 修改属于其他包管理器的系统包。
对于您自己的 Python 项目,请使用独立的虚拟环境。如果要安装命令行应用程序,pipx 可以让它与系统 Python 隔离开来。欢迎加入我们的Discord 频道,获取更多关于 Python 报错与修复的技巧。