返回博客

如何修复 Python 中的 externally-managed-environment 错误

-
目录
-

核心要点:

  • 修复 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 环境保持整洁、互不干扰的建议:

  1. 为每个 Python 项目使用独立的虚拟环境,例如我们关于 Python 网络爬取的指南展示了如何创建环境并添加爬虫所需的库
  2. 在使用 pip 安装软件包之前,请先激活虚拟环境
  3. 如果想确保 pip 与您正在使用的解释器保持关联,可以使用 python -m pip
  4. 将项目依赖记录在 requirements.txt 或 pyproject.toml 等文件中
  5. 对于属于操作系统的软件包,应使用 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 解释器
  • .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 报错与修复的技巧。

了解更多
-

相关文章