pip install で externally-managed-environment エラーが出たときの直し方

Ubuntu 23.04以降でpip installを叩くと、こんなエラーが出るようになった。

error: externally-managed-environment
× This environment is externally managed
╰─> To install Python packages system-wide, use apt.

直し方は2つあって、正解はvenvを使うことだ。--break-system-packages を使う方法も動くが、名前が示す通りシステムを壊しにいくオプションなので常用には向かない。

なぜ急にエラーが出るようになったのか

Python 3.11 から適用された PEP 668 が原因だ。

Ubuntu がシステム全体の Python 環境をパッケージマネージャ(apt)で管理するようになり、pip による直接インストールを意図的に禁止した。2023年4月リリースの Ubuntu 23.04 でこの制約が有効になり、同じく Debian 12(Bookworm) も同時期に追随している。

問題が起きやすいのは、旧来のチュートリアル通りに pip install を打つケースだ。2022年以前のブログ記事や README には普通に pip install requests と書いてあって、それをそのまま実行するとエラーになる。書いた人が悪いわけではなく、当時は動いていたので仕方ない。

venvを使うのが正しい対処

仮想環境を作って、その中でpipを使う方法がPEP 668 の本来の意図に沿った解決策だ。

Terminal window
python3 -m venv .venv
source .venv/bin/activate
pip install requests # エラーなく動く

.venv という名前は慣習で、プロジェクトルートに置くのが普通だ。deactivate で抜けられる。毎回 source .venv/bin/activate が面倒なら、シェルの設定ファイルにパスを足すか、direnv を使うと自動化できる。

プロジェクトをまたいで使いたいツール(black、ruff、httpieなど)は、pipx を使うと各ツールが独立した仮想環境に入るので管理が楽になる。

Terminal window
sudo apt install pipx
pipx install black

—break-system-packages は一時しのぎ

pip install --break-system-packages requests でもエラーは消える。オプション名が正直すぎて笑えるが、やっていることは「このシステム、壊れてもいいよ」と宣言してインストールを強行することだ。

スクリプトのワンライナーで試すときや、捨てるつもりのDockerコンテナ内なら使えなくはない。ただし本番環境や長く使うマシンには使わない方がいい。aptで入れたパッケージと pip で入れたパッケージが干渉して、apt upgrade のタイミングで壊れるパターンが実際にある。

sudoをつけても解決しない

sudo pip install を試す人も多いが、これは動かない。sudo をつけても同じエラーが出る。PEP 668 の制約はrootでも適用される設計になっているためで、権限の問題ではない。

古い記事に「sudo をつければ動く」と書いてあっても、Ubuntu 23.04以降では通用しない。

venvを使うと何が変わるか

仮想環境の中では pip が自由に使える。インストール先が .venv/lib/python3.x/site-packages/ に限定されるので、システムのPythonには一切干渉しない。プロジェクトを削除するときは .venv ごと消せばきれいになる。

requirements.txt や pyproject.toml との組み合わせも自然で、pip freeze > requirements.txt したものを別のマシンで pip install -r requirements.txt するときも venv の中でやれば再現性が高い。

externally-managed-environment エラーは「邪魔なエラー」ではなく、システムを守るための設計変更だ。venvに慣れると、むしろ環境が汚れにくくなって快適になる。