İçeriğe geç
KURUMSAL Kurumsal teknoloji · İşletmenize özel mühendislik Kurumsal Yazılım · Yönetilen Sunucular · Kurumsal E-posta · LiteSpeed + CloudLinux · Imunify360 Güvenlik · cPanel Yönetim · Uygun pakette 3 Gbps'ye kadar ağ profili
AIOR

Python externally-managed-environment Hatası: venv, pipx, uv ile Çözüm

  • Konu başlatıcısı Konu başlatıcısı Aior
  • Başlangıç tarihi Başlangıç tarihi

Aior

Administrator

Yetkili üye
Katıldı
2 Nis 2023
Mesajlar
929
Tepki puanı
2
Puan
18
Yaş
41
Konum
Turkey
Web sitesi
aior.com
Konu sahibi

Debian 12 ya da Ubuntu 24.04 çalışan bir sunucuda, Bookworm yüklü bir Raspberry Pi'da veya Homebrew Python kullanan bir Mac'te pip install komutunu çalıştırdığınızda pip paketi kurmak yerine error: externally-managed-environment hatası verir. Ortada bir arıza yok: işletim sistemi kendi Python kurulumunu koruyor. Doğru çözüm neyi kurduğunuza bağlıdır: proje bağımlılığı, komut satırı aracı, zamanlanmış betik, Docker imajı ya da CI işi. Bu rehberde Ubuntu ve Debian'daki bu pip install hatasının nedenini ve her durum için doğru yolu adım adım anlatıyoruz.

Hata mesajı​

Debian ve Ubuntu'da çıktı şöyledir (README yolundaki Python sürümü dağıtım sürümüne göre değişir):

Kod:
$ pip install PyMuPDF Pillow
error: externally-managed-environment

× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
    python3-xyz, where xyz is the package you are trying to
    install.

    If you wish to install a non-Debian-packaged Python package,
    create a virtual environment using python3 -m venv path/to/venv.
    Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
    sure you have python3-full installed.

    If you wish to install a non-Debian packaged Python application,
    it may be easiest to use pipx install xyz, which will manage a
    virtual environment for you. Make sure you have pipx installed.

    See /usr/share/doc/python3.12/README.venv for more information.

note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
hint: See PEP 668 for the detailed specification.

Homebrew, Arch Linux ve Alpine farklı bir metin gösterir (brew, pacman ve apk önerilir), ama mekanizma aynıdır.

Neden oluyor: PEP 668 ve EXTERNALLY-MANAGED dosyası​

Linux dağıtımlarında sistem Python'u paket yöneticisine aittir. apt; python3-yaml, python3-requests gibi paketleri /usr/lib/python3/dist-packages altına kurar ve add-apt-repository, unattended-upgrades, cloud-init gibi Python ile yazılmış sistem araçları tam da bu sürümlerle test edilir. pip aynı kütüphanenin başka bir sürümünü sudo ile /usr/local altına ya da --user ile ~/.local altına kurduğunda, içe aktarma (import) sırasında önce o kopya bulunur. apt bundan habersizdir ve bir sonraki güncellemede bir sistem aracı bozulabilir.

2022'de kabul edilen PEP 668, dağıtımlara basit bir anahtar sunar: yorumlayıcının (interpreter) standart kütüphane dizinine konan EXTERNALLY-MANAGED adlı bir işaret dosyası (marker file). pip 23.0 ve sonrası, bu dosyayı taşıyan bir yorumlayıcıya sanal ortam dışında paket kurmayı reddeder; --break-system-packages seçeneği ise pip 23.0.1 ile eklendi. Kontrol --user kurulumlarını da kapsar, sanal ortamın içinde ise hiç devreye girmez. Yorumlayıcınızın işaretli olup olmadığını şöyle görebilirsiniz:

Bash:
python3 -c 'import os, sysconfig; p = os.path.join(sysconfig.get_path("stdlib"), "EXTERNALLY-MANAGED"); print(p, os.path.exists(p))'
# /usr/lib/python3.12/EXTERNALLY-MANAGED True

Platformİşaretli mi?Not
Debian 12 (bookworm) ve sonrasıEvetpython3-venv, pipx ve python3-xyz paketleri depoda
Ubuntu 23.04 ve sonrası (24.04 LTS dahil)EvetPaketleme Debian ile aynı
Raspberry Pi OS Bookworm ve sonrasıEvetResmi dokümantasyon pip için venv şart koşuyor
Homebrew Python (macOS ve Linux)Evetbrew install pipx
Arch Linux, güncel Alpine sürümleriEvetpython-xyz (pacman), py3-xyz (apk)
Fedora, AlmaLinux, Rocky LinuxBu yazı hazırlanırken hayırpip reddetmez; yine de venv önerilir
python.org kurulumları, pyenv derlemeleri, resmi python Docker imajlarıHayırBir işletim sistemi paket yöneticisine ait değil

Dağıtımların paketleme kararları zamanla değişebilir; kendi makinenizde kesin cevabı yukarıdaki tek satırlık komut verir.

Hangi durumda hangi çözüm?​

Ne kuruyorsunuz?AraçÖrnek
Bir proje ya da betik için kütüphanelervenvpython3 -m venv .venv
Her terminalde çalışacak bir komut satırı uygulamasıpipx (veya uv tool)pipx install yt-dlp
Dağıtımın zaten paketlediği bir kütüphaneaptsudo apt install python3-requests
Çok sayıda proje, hızlı kurulum, birden fazla Python sürümüuvuv venv, ardından uv pip install -r requirements.txt
Docker imajıResmi python imajı ya da imaj içinde venvFROM python:3.12-slim
CI işisetup-python, python imajı ya da venvactions/setup-python
Başka yol kalmadığında, tek kullanımlık bir konteyner--break-system-packages (son çare)pip install --break-system-packages x

Çözüm 1: Python sanal ortam (venv) oluşturma, adım adım​

Gerekli paketleri kurun​

Debian ve Ubuntu'da venv, yeni ortamlara pip yükleyen ensurepip bileşeni için python3-venv paketine ihtiyaç duyar; python3-full ise standart kütüphanenin tamamını kurar. Sistem geneline python3-pip kurmanız gerekmez, çünkü her sanal ortam kendi pip'iyle gelir. Homebrew ve Arch'ta venv zaten hazırdır.

Bash:
sudo apt update
sudo apt install python3-venv     # ya da python3-full

Oluşturun ve etkinleştirin​

Bash:
cd ~/projeler/uygulamam
python3 -m venv .venv
source .venv/bin/activate         # bash ve zsh
# fish:        source .venv/bin/activate.fish
# PowerShell:  .venv\Scripts\Activate.ps1   (Linux/macOS'ta pwsh: .venv/bin/Activate.ps1)
# Windows cmd: .venv\Scripts\activate.bat
which python                      # .../uygulamam/.venv/bin/python göstermeli

Etkinleştirme (activate) bir kolaylıktır, zorunlu değildir: .venv/bin dizinini PATH'in başına ekler, VIRTUAL_ENV değişkenini tanımlar ve komut istemini değiştirir. PowerShell betik çalıştırmanın devre dışı olduğunu söylerse bir kez Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser komutunu çalıştırın.

Kurun, kaydedin, çıkın​

Bash:
python -m pip install requests
python -m pip freeze > requirements.txt     # sürümleri sabitleyin
python -m pip install -r requirements.txt   # başka makinede aynı ortamı kurun
deactivate

Git deposuna .venv klasörünü değil, requirements.txt dosyasını ekleyin (Python 3.13 ve sonrası venv klasörünün içine kendiliğinden bir .gitignore yazar; eski sürümlerde .venv/ satırını projenin .gitignore dosyasına kendiniz ekleyin). Sanal ortam mutlak yollar içerdiği için kopyalanmaz ya da taşınmaz; requirements.txt dosyasından yeniden oluşturulur.

Editörü sanal ortama yönlendirin​

VS Code'da Komut Paleti'nden "Python: Select Interpreter" komutunu çalıştırıp ./.venv/bin/python yorumlayıcısını seçin. PyCharm'da Settings > Python > Interpreter ekranını açın (eski sürümlerde Settings > Project > Python Interpreter), ardından Add Interpreter > Add Local Interpreter adımlarıyla mevcut .venv/bin/python dosyasını gösterin. Kod terminalde çalışıyor ama editör import satırlarını çözümlenemeyen (unresolved import) olarak işaretliyorsa, editör hâlâ sistem yorumlayıcısını kullanıyordur.

Uygulamalı örnek: PyMuPDF ile PDF'ten JPG'ye​

Python ile PDF sayfalarını JPG'ye dönüştürme rehberimiz pip install PyMuPDF Pillow komutuyla başlıyor; Ubuntu 24.04'te hata veren komut da tam olarak bu. Sorunsuz çalışan adımlar şöyle:

Bash:
sudo apt install python3-venv
mkdir -p ~/projeler/pdf-jpg && cd ~/projeler/pdf-jpg
python3 -m venv .venv
source .venv/bin/activate
python -m pip install PyMuPDF Pillow
python -m pip show PyMuPDF | grep Location   # .../pdf-jpg/.venv/lib/python3.12/site-packages
python -m pip freeze > requirements.txt

Aynı işi pdf2image ile yaparsanız iş bölümü netleşir: pdf2image arka planda Poppler komut satırı araçlarını çağırır; bu yüzden poppler-utils apt ile, Python sarmalayıcısı (wrapper) ise venv içine kurulur. Sistem programları paket yöneticisinden, Python kütüphaneleri sanal ortama: bu kural durumların çoğunu çözer.

Çözüm 2: Komut satırı uygulamaları için pipx kurulumu​

pipx her uygulamaya ayrı, gizli bir sanal ortam açar ve yalnızca uygulamanın komutlarını ~/.local/bin dizinine bağlantı (link) olarak ekler. yt-dlp, black ya da httpie gibi her terminalden çalıştırdığınız ama kendi kodunuzda import etmediğiniz araçlar için doğru seçim budur.

Bash:
sudo apt install pipx         # macOS: brew install pipx
pipx ensurepath               # ~/.local/bin dizinini PATH'e ekler; yeni terminal açın
pipx install yt-dlp
pipx list
pipx run pycowsay moo         # geçici bir ortamda tek seferlik çalıştırma
pipx upgrade-all
pipx reinstall-all            # sistemdeki Python sürümü değiştikten sonra

pipx kütüphaneleri import edilebilir hâle getirmez: betiğinizde import requests satırı varsa ihtiyacınız olan şey bir sanal ortamdır.

Çözüm 3: uv ile hızlı iş akışı​

Astral'ın geliştirdiği uv; pip, venv ve pipx'in işlerini tek bir ikili dosyada (binary) toplar ve paketleri çok daha hızlı kurar. İşaret dosyasına o da uyar: uv pip install varsayılan olarak bir sanal ortam bekler; --system ya da --python ile sistem yorumlayıcısını hedeflediğinizde bile --break-system-packages vermedikçe harici olarak yönetilen bir yorumlayıcıyı değiştirmez.

Bash:
curl -LsSf https://astral.sh/uv/install.sh | sh   # ya da: brew install uv / pipx install uv
uv venv                            # bulunduğunuz dizinde .venv oluşturur
uv pip install -r requirements.txt # etkinleştirmeden de .venv klasörünü bulur
uv tool install ruff               # pipx gibi CLI uygulamaları için
uvx ruff check .                   # kurmadan tek seferlik çalıştırma
uv tool upgrade --all

Bir tuzak: uv venv ortamın içine pip koymaz. Ortamı etkinleştirip düz pip install yazarsanız kabuk sistemdeki pip'i bulur ve aynı hatayla yeniden karşılaşırsınız. uv pip install kullanın ya da ortamı uv venv --seed ile oluşturun. Kilit dosyalı (lockfile) proje akışı (uv init, uv add, uv sync) uv dokümantasyonunda anlatılıyor; uv'nin bağımlılık kilitleme ve daha küçük konteyner imajları için nasıl kullanıldığına ise FastAPI ve Django üzerine Python backend notlarımızda değindik.

Dağıtım paketleri: apt install python3-xyz​

Kütüphane dağıtımda paketlenmişse, onu sistem Python'una eklemenin desteklenen yolu apt ile kurmaktır; güvenlik düzeltmeleri de normal güncellemelerle gelir. Debian ailesinde paket adları python3-xyz kalıbını izler: python3-requests, python3-yaml (PyYAML), python3-pil (Pillow), python3-serial (pyserial). Paketin var olup olmadığını apt-cache policy python3-serial ile kontrol edin. Karşılığında daha eski sürümlerle yetinirsiniz, çünkü paket sürümleri dağıtım sürümüne bağlıdır.

Raspberry Pi'da bazı donanım kütüphanelerini apt ile kurmak daha doğrudur; örneğin Picamera2 projesi, sistemdeki libcamera ile uyumlu sürümü almak için sudo apt install python3-picamera2 komutunu öneriyor. --system-site-packages ile oluşturulan bir sanal ortam bu modülleri görür, pip ise geri kalan her şeyi venv içine kurar:

Bash:
python3 -m venv --system-site-packages .venv

cron, systemd ve sudo​

Zamanlanmış betiklerin sanal ortamı etkinleştirmesi gerekmez; venv içindeki python kendi ortamını bilir, onu mutlak yoluyla çağırmanız yeterli:

Bash:
# crontab -e
*/15 * * * * /home/deploy/pdf-jpg/.venv/bin/python /home/deploy/pdf-jpg/donustur.py >> /home/deploy/pdf-jpg/cron.log 2>&1

INI:
# /etc/systemd/system/pdf-jpg.service
[Unit]
Description=PDF to JPG converter

[Service]
Type=oneshot
User=deploy
WorkingDirectory=/home/deploy/pdf-jpg
ExecStart=/home/deploy/pdf-jpg/.venv/bin/python /home/deploy/pdf-jpg/donustur.py

Bir servisin sanal ortamını o servisi çalıştıracak hesapla oluşturun (sudo -u deploy python3 -m venv /home/deploy/pdf-jpg/.venv); böylece dosyalar root'a ait olmaz. Type=oneshot, bir systemd zamanlayıcısıyla (timer) ya da elle başlatılan işler içindir; sürekli çalışan bir servis için Type=simple kullanın ve WantedBy=multi-user.target satırını içeren bir Install bölümü ekleyin.

sudo, yönetim komutları için doğru araçtır; "Bu komut süper kullanıcı (root) yetkisiyle çalıştırılmalıdır" hatası rehberimizde bunu ayrıntısıyla anlattık. Ancak bu sistemlerde pip bir yönetim komutu değildir. Başına sudo eklemek bu hatayı aşmanızı sağlamaz, çünkü kontrol root için de geçerlidir. Kurulumun geçtiği durumlarda (--break-system-packages ile ya da işaret dosyası olmayan bir sürümde) ise sudo pip install root olarak sistem dizinine yazar ve sizin paketlerinizi dağıtımın paketleriyle karıştırır. Üstelik Debian ve Ubuntu'da sudo, PATH değişkenini sabit bir secure_path ile değiştirir; etkin bir venv içindeyken sudo pip yazarsanız çalışan, sistemdeki pip olur. Bir sanal ortama yazmak root yetkisi istiyorsa ortamın sahipliğini düzeltin.

Docker ve CI​

Konteynerde en basit çözüm resmi python imajıdır: bu imajdaki yorumlayıcı /usr/local altına derlenmiştir ve işaret dosyası taşımaz, pip her zamanki gibi çalışır.

Kod:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]

İmajda dağıtımın kendi Python'unu kullanmak zorundaysanız imajın içinde bir venv oluşturup PATH'in başına koyun; sonraki tüm RUN, CMD ve docker exec komutları etkinleştirme gerekmeden bu ortamı kullanır:

Kod:
FROM debian:trixie-slim
RUN apt-get update && apt-get install -y --no-install-recommends python3 python3-venv \
    && rm -rf /var/lib/apt/lists/*
RUN python3 -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

GitHub Actions'ta actions/setup-python ile kurulan yorumlayıcı işaretli değildir:

YAML:
steps:
  - uses: actions/checkout@v7
  - uses: actions/setup-python@v7
    with:
      python-version: "3.12"
  - run: python -m pip install -r requirements.txt
  - run: python -m pytest

GitHub'ın kendi Ubuntu 24.04 ve sonrası runner imajları şu an /etc/pip.conf dosyasına break-system-packages = true yazıyor (actions/runner-images derleme betikleri); bu yüzden orada düz pip install hata vermez. GitHub'ın barındırdığı runner'da sorunsuz geçen bir iş akışının düz bir ubuntu:24.04 konteynerinde ya da kendi barındırdığınız (self-hosted) bir runner'da bu hatayla durmasının nedeni budur. Bu ortamlarda /usr/bin/python3 kullanan işler ilk adımda bir venv oluşturmalıdır. GitLab CI'da image: python:3.12-slim, setup-python'ın gördüğü işi görür.

Yapmamanız gerekenler ve son çare​

  • EXTERNALLY-MANAGED dosyasını silmek. Uyarıyı kaldırır, çakışmayı değil. Debian'ın README.venv belgesi dosyayı dpkg-divert ile kenara almayı yalnızca "riski size ait olmak üzere" tarif eder; bakımını yaptığınız bir makinede yapmayın.
  • Kontrolü aşarak sudo pip install çalıştırmak. Paketler /usr/local/lib/python3.X/dist-packages altına gider ve içe aktarma sırasında apt tarafından yönetilen /usr/lib/python3/dist-packages dizininden önce gelir; böylece sistem araçlarının test edildiği sürümleri gölgeler.
  • --user seçeneğini güvenli yol sanmak. ~/.local altındaki paketler, dağıtım araçları dahil hesabınızla çalışan Python programlarına görünür; PEP 668 bu yüzden onu da engeller.
  • Kontrolü genel olarak kapatmak. pip.conf içine break-system-packages = true yazmak ya da PIP_BREAK_SYSTEM_PACKAGES=1 tanımlamak, sonraki tüm kurulumların kontrolü sessizce atlamasına yol açar.

--break-system-packages ancak tek kullanımlık bir CI konteynerinde ya da her seferinde sıfırdan üretilen ve apt ile güncellenmeyen bir imajda savunulabilir. Orada bile venv yalnızca bir satır fazlasına mal olur.

sudo pip ile bozulmuş sistem Python'unu onarma​

Tipik belirtiler: apt ile ilgili bir betik ImportError verir ya da pip bağımlılıklarından birini yükselttikten sonra bir sistem aracı çalışmaz hâle gelir. Debian ve Ubuntu'da:

Bash:
PYV=$(python3 -c 'import sys; print(f"{sys.version_info[0]}.{sys.version_info[1]}")')
ls /usr/local/lib/python$PYV/dist-packages/            # sudo pip ile kurulanlar
ls ~/.local/lib/python$PYV/site-packages/ 2>/dev/null  # --user ile kurulanlar

python3 -m pip freeze --path /usr/local/lib/python$PYV/dist-packages > ~/sudo-pip.txt
sudo python3 -m pip uninstall --break-system-packages -y -r ~/sudo-pip.txt
mv ~/.local/lib/python$PYV ~/.local/lib/python$PYV.yedek   # geri alınabilir

dpkg -S EXTERNALLY-MANAGED                   # işaret dosyası hangi pakete ait
sudo apt install --reinstall python3-yaml    # bozulan her python3-* paketi için tekrarlayın
dpkg --verify python3-yaml                   # çıktı yoksa dosyalar sağlam

İşaret dosyası silindiyse dpkg -S komutunun gösterdiği paketi yeniden kurun; dpkg-divert ile kenara alındıysa sudo dpkg-divert --rename --remove komutuna dosyanın yolunu vererek geri alın. Son olarak kaydettiğiniz listeyi, o paketlere gerçekten ihtiyaç duyan projelerin sanal ortamlarına kurun.

İlgili hatalar​

  • "ensurepip is not available" (venv oluştururken): mesajın adını verdiği paketi (python3-venv ya da python3.12-venv gibi sürüme özel olanı) kurun, yarım kalan .venv klasörünü silin ve yeniden oluşturun.
  • "No module named venv": büyük ihtimalle Python 2'yi ya da eksik kurulmuş bir yorumlayıcıyı çağırıyorsunuz. python3 --version ile kontrol edin; Debian ve Ubuntu'da python3-full standart kütüphanenin tamamını getirir.
  • pip: command not found: temiz bir Debian ya da Ubuntu kurulumunda normaldir, çünkü pip komutu ayrı bir paket olan python3-pip ile gelir. venv ile çalışırken buna ihtiyacınız yoktur: etkin bir venv içinde pip zaten vardır.
  • pip ile python farklı yorumlayıcıları gösteriyor: pip --version, pip'in hangi Python'a ait olduğunu yazar; python -m pip ise her zaman çağırdığınız python ile eşleşir.
  • Etkinleştirme işe yaramıyor: bash .venv/bin/activate komutu ayrı bir kabuk sürecinde çalışıp hemen kapanır. source kullanın; bash'te önbellekteki eski komut yolunu hash -r temizler.
  • İşletim sistemi yükseltmesinden sonra venv bozuldu (bad interpreter, No such file or directory): ortamın dayandığı Python değişti. .venv klasörünü silip requirements.txt dosyasından yeniden kurun; pipx için pipx reinstall-all çalıştırın.

Sık sorulan sorular​

Bu hata sistemimdeki bir arıza mı?
Hayır. Debian, Ubuntu, Raspberry Pi OS, Homebrew ve diğerleri bu korumayı bilerek açtı; amaç pip ile sistem paket yöneticisinin birbirinin dosyalarını ezmesini önlemek.

--break-system-packages eklesem olmaz mı?
Olur, ama bunu tek kullanımlık sistemlere bırakın. Bakımını yaptığınız bir sunucuda bugünkü bir dakikalık çözüm, ileride izini sürmesi zor bir arızaya dönüşebilir.

Her proje için ayrı bir venv mi gerekiyor?
Evet: her projeye bir .venv ve bir requirements.txt. Böylece bir projeyi güncellemek diğerini bozmaz.

pipx mi, uv tool mu?
İkisi de komut satırı uygulamalarını yalıtılmış ortamlara kurar. pipx çoğu dağıtımın deposunda bulunur ve güvenli bir varsayılandır; uv'yi zaten kullanıyorsanız uv tool daha hızlıdır.

Windows'ta da bu hatayı alır mıyım?
python.org kurulum programıyla hayır, o yorumlayıcı işaretli değildir. WSL içinde ise alırsınız: WSL altında çalışan bir Ubuntu 24.04, Ubuntu'nun kendi işaretli Python'unu kullanır. venv akışı iki ortamda da aynıdır ve projeleri birbirinden ayırmanın en temiz yoludur.

Sonuç ve sonraki adımlar​

Bu hata, işletim sisteminin "paketlerini benim Python'umdan uzak tut" demesidir. Aracı işe göre seçin: proje kütüphaneleri için venv, komut satırı uygulamaları için pipx ya da uv tool, dağıtımın sunduğu kütüphaneler için apt, konteynerlerde ise resmi python imajı veya imaj içinde venv. Sıradaki adımlar: mevcut projeniz için bir .venv oluşturun, requirements.txt dosyasını kaydedin ve cron satırlarınızla systemd birimlerinizi .venv/bin/python yolunu tam haliyle çağıracak şekilde güncelleyin. Python servislerinizi çalıştıracak bir sunucu arıyorsanız AIOR'un sanal sunucu (VPS) paketleri seçeneklerden biri. Kendi kurulumunuza özel sorularınızı bu konuya yazabilirsiniz.

You run pip install on a Debian 12 or Ubuntu 24.04 server, a Raspberry Pi with Bookworm or a Mac with Homebrew Python, and instead of installing anything pip stops with error: externally-managed-environment. Nothing is broken: the operating system is protecting its own Python. The right fix depends on what you are installing (a project dependency, a command-line tool, a scheduled script, a Docker image or a CI job), and this guide covers each case.

The error message​

On Debian and Ubuntu it looks like this (the version in the README path varies by release):

Kod:
$ pip install PyMuPDF Pillow
error: externally-managed-environment

× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
    python3-xyz, where xyz is the package you are trying to
    install.

    If you wish to install a non-Debian-packaged Python package,
    create a virtual environment using python3 -m venv path/to/venv.
    Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
    sure you have python3-full installed.

    If you wish to install a non-Debian packaged Python application,
    it may be easiest to use pipx install xyz, which will manage a
    virtual environment for you. Make sure you have pipx installed.

    See /usr/share/doc/python3.12/README.venv for more information.

note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
hint: See PEP 668 for the detailed specification.

Homebrew, Arch Linux and Alpine word it differently (brew, pacman, apk), but the mechanism is the same.

Why it happens: PEP 668 and the EXTERNALLY-MANAGED file​

On a Linux distribution the system Python belongs to the package manager. apt installs python3-yaml, python3-requests and the like under /usr/lib/python3/dist-packages, and Python-based system tools such as add-apt-repository, unattended-upgrades and cloud-init are tested against exactly those versions. When pip installs a different version with sudo (into /usr/local) or with --user (into ~/.local), that copy wins at import time, apt knows nothing about it, and a system tool can break at the next upgrade.

PEP 668, accepted in 2022, gives distributions a simple switch: a file named EXTERNALLY-MANAGED in the interpreter's standard library directory. pip 23.0 and later refuse to install into such an interpreter outside a virtual environment, and pip 23.0.1 added the --break-system-packages override. The check covers --user installs too and never applies inside a venv. To see whether your interpreter is marked:

Bash:
python3 -c 'import os, sysconfig; p = os.path.join(sysconfig.get_path("stdlib"), "EXTERNALLY-MANAGED"); print(p, os.path.exists(p))'
# /usr/lib/python3.12/EXTERNALLY-MANAGED True

PlatformMarked?Notes
Debian 12 (bookworm) and laterYespython3-venv, pipx and python3-xyz in the archive
Ubuntu 23.04 and later, including 24.04 LTSYesSame packaging as Debian
Raspberry Pi OS Bookworm and laterYesOfficial docs require a venv for pip
Homebrew Python (macOS and Linux)Yesbrew install pipx
Arch Linux, current Alpine releasesYespython-xyz (pacman), py3-xyz (apk)
Fedora, AlmaLinux, Rocky LinuxNo, at the time of writingpip doesn't refuse; a venv is still advisable
python.org installers, pyenv builds, official python Docker imagesNoNot owned by an OS package manager

Packaging changes over time, so the one-liner above is the real test on your own machine.

Which fix for which situation​

What you are installingUseExample
Libraries for a project or scriptvenvpython3 -m venv .venv
A command-line app you want in every terminalpipx (or uv tool)pipx install yt-dlp
A library the distribution already shipsaptsudo apt install python3-requests
Many projects, fast installs, several Python versionsuvuv venv, then uv pip install -r requirements.txt
A Docker imageOfficial python image, or a venv inside the imageFROM python:3.12-slim
A CI jobsetup-python, a python image or a venvactions/setup-python
A disposable container when nothing else fits--break-system-packages (last resort)pip install --break-system-packages x

Fix 1: a virtual environment (venv), step by step​

Install the prerequisites​

On Debian and Ubuntu, venv needs python3-venv, which provides ensurepip to seed pip into new environments; python3-full installs the whole standard library. You don't need python3-pip system-wide, since every venv gets its own pip. Homebrew and Arch include venv already.

Bash:
sudo apt update
sudo apt install python3-venv     # or python3-full

Create and activate​

Bash:
cd ~/projects/myapp
python3 -m venv .venv
source .venv/bin/activate         # bash and zsh
# fish:        source .venv/bin/activate.fish
# PowerShell:  .venv\Scripts\Activate.ps1   (pwsh on Linux/macOS: .venv/bin/Activate.ps1)
# Windows cmd: .venv\Scripts\activate.bat
which python                      # should print .../myapp/.venv/bin/python

Activation is a convenience, not a requirement: it puts .venv/bin first on PATH, sets VIRTUAL_ENV and changes the prompt. If PowerShell says running scripts is disabled, run Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser once.

Install, record, leave​

Bash:
python -m pip install requests
python -m pip freeze > requirements.txt     # pin exact versions
python -m pip install -r requirements.txt   # rebuild on another machine
deactivate

Commit requirements.txt, not .venv (Python 3.13 and later write a .gitignore inside the venv; on older versions add .venv/ to your .gitignore yourself). A venv contains absolute paths, so you don't copy or move it; you recreate it from requirements.txt.

Point your editor at the venv​

In VS Code, run "Python: Select Interpreter" from the Command Palette and choose ./.venv/bin/python. In PyCharm, open Settings > Python > Interpreter (Settings > Project > Python Interpreter in older releases), click Add Interpreter > Add Local Interpreter and select the existing .venv/bin/python. If code runs in the terminal but the editor flags unresolved imports, the editor is still on the system interpreter.

Worked example: PyMuPDF for PDF to JPG​

Our PDF to JPG with Python guide starts with pip install PyMuPDF Pillow, exactly the command that fails on Ubuntu 24.04. The working sequence:

Bash:
sudo apt install python3-venv
mkdir -p ~/projects/pdf-jpg && cd ~/projects/pdf-jpg
python3 -m venv .venv
source .venv/bin/activate
python -m pip install PyMuPDF Pillow
python -m pip show PyMuPDF | grep Location   # .../pdf-jpg/.venv/lib/python3.12/site-packages
python -m pip freeze > requirements.txt

With pdf2image instead, the division of labour is easy to see: it calls the Poppler command-line tools, so poppler-utils comes from apt and the Python wrapper goes into the venv. System programs from the package manager, Python libraries in the venv: that rule settles most cases.

Fix 2: pipx for command-line applications​

pipx gives every application its own hidden venv and links only its commands into ~/.local/bin. Use it for tools such as yt-dlp, black or httpie that you run from any terminal but never import in your own code.

Bash:
sudo apt install pipx         # macOS: brew install pipx
pipx ensurepath               # puts ~/.local/bin on PATH; open a new terminal
pipx install yt-dlp
pipx list
pipx run pycowsay moo         # run once in a temporary environment
pipx upgrade-all
pipx reinstall-all            # after the system Python version changes

pipx doesn't make libraries importable: if your script says import requests, you need a venv.

Fix 3: uv, the fast all-in-one tool​

uv, from Astral, does the jobs of pip, venv and pipx in one binary and installs packages much faster. It respects the marker too: uv pip install expects a virtual environment by default, and even when you point it at the system interpreter (with --system or --python) it refuses to modify an externally managed one without --break-system-packages.

Bash:
curl -LsSf https://astral.sh/uv/install.sh | sh   # or: brew install uv / pipx install uv
uv venv                            # creates .venv in the current directory
uv pip install -r requirements.txt # finds .venv even without activation
uv tool install ruff               # CLI apps, like pipx
uvx ruff check .                   # run once without installing
uv tool upgrade --all

One trap: uv venv doesn't put pip into the environment, so after activating it a plain pip install finds the system pip and you get the same error. Use uv pip install, or create the environment with uv venv --seed. Lockfile-based projects (uv init, uv add, uv sync) are covered in the uv documentation, and our Python backend notes on FastAPI and Django cover uv for dependency locking and slimmer container builds.

Distribution packages: apt install python3-xyz​

If the distribution already packages a library, apt is the supported way to add it to the system Python, and security fixes arrive with normal upgrades. Debian-family names follow the python3-xyz pattern: python3-requests, python3-yaml (PyYAML), python3-pil (Pillow), python3-serial (pyserial). Check availability with apt-cache policy python3-serial. The trade-off is age: versions are tied to the distribution release.

On a Raspberry Pi some hardware libraries are best taken from apt: the Picamera2 project, for example, recommends sudo apt install python3-picamera2 so that it matches the system's libcamera. A venv created with --system-site-packages sees those modules while pip still installs everything else into the venv:

Bash:
python3 -m venv --system-site-packages .venv

Cron, systemd and sudo​

Scheduled scripts don't need activation; the venv's python knows its environment, so call it by absolute path:

Bash:
# crontab -e
*/15 * * * * /home/deploy/pdf-jpg/.venv/bin/python /home/deploy/pdf-jpg/convert.py >> /home/deploy/pdf-jpg/cron.log 2>&1

INI:
# /etc/systemd/system/pdf-jpg.service
[Unit]
Description=PDF to JPG converter

[Service]
Type=oneshot
User=deploy
WorkingDirectory=/home/deploy/pdf-jpg
ExecStart=/home/deploy/pdf-jpg/.venv/bin/python /home/deploy/pdf-jpg/convert.py

Create a service's venv as the account that runs it (sudo -u deploy python3 -m venv /home/deploy/pdf-jpg/.venv) so its files aren't owned by root. Type=oneshot suits a job started by a systemd timer or by hand; for a long-running service use Type=simple and add an Install section with WantedBy=multi-user.target.

sudo is the right tool for administrative commands, as our guide to the "This command must be run as root" error explains, but here pip is not one of them. sudo doesn't get you past this error, because the check applies to root as well. Where an install does go through (with the override, or on a release without the marker), sudo pip install writes into the system location as root and mixes your packages with the distribution's. On Debian and Ubuntu, sudo also swaps PATH for a fixed secure_path, so sudo pip inside an activated venv runs the system pip. If writing to a venv needs root, fix the venv's ownership instead.

Docker and CI​

The simplest container fix is the official python image: its interpreter is compiled into /usr/local without a marker, so pip works as usual.

Kod:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]

If the image must use the distribution's Python, create a venv in the image and put it first on PATH; every later RUN, CMD and docker exec uses it without activation:

Kod:
FROM debian:trixie-slim
RUN apt-get update && apt-get install -y --no-install-recommends python3 python3-venv \
    && rm -rf /var/lib/apt/lists/*
RUN python3 -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

In GitHub Actions, the interpreter from actions/setup-python isn't marked:

YAML:
steps:
  - uses: actions/checkout@v7
  - uses: actions/setup-python@v7
    with:
      python-version: "3.12"
  - run: python -m pip install -r requirements.txt
  - run: python -m pytest

GitHub's own Ubuntu 24.04 and newer runner images currently write break-system-packages = true into /etc/pip.conf (see the actions/runner-images build scripts), so a bare pip install doesn't complain there. That is why a workflow that passes on a GitHub-hosted runner can stop with this error in a plain ubuntu:24.04 container or on a self-hosted runner; jobs that use /usr/bin/python3 in those places should create a venv first. In GitLab CI, image: python:3.12-slim does the job of setup-python.

What not to do, and the last resort​

  • Deleting EXTERNALLY-MANAGED. It removes the warning, not the conflict. Debian's README.venv describes diverting the file with dpkg-divert strictly at your own risk; on a machine you maintain, don't.
  • sudo pip install with the override. Packages land in /usr/local/lib/python3.X/dist-packages, which comes before the apt-managed /usr/lib/python3/dist-packages on the import path, so they shadow the versions your system tools were tested with.
  • Treating --user as safe. Packages in ~/.local are visible to the Python programs your account runs, distribution tools included; that is why PEP 668 blocks them too.
  • Disabling the check globally with break-system-packages = true in pip.conf or PIP_BREAK_SYSTEM_PACKAGES=1. Every later install then bypasses it silently.

--break-system-packages is defensible in a throwaway CI container or an image rebuilt from scratch and never upgraded with apt. Even there, a venv costs one extra line.

Repairing a system Python that sudo pip has damaged​

Typical symptoms: an apt-related script fails with ImportError, or a system tool breaks after pip upgraded one of its dependencies. On Debian and Ubuntu:

Bash:
PYV=$(python3 -c 'import sys; print(f"{sys.version_info[0]}.{sys.version_info[1]}")')
ls /usr/local/lib/python$PYV/dist-packages/            # installed by sudo pip
ls ~/.local/lib/python$PYV/site-packages/ 2>/dev/null  # installed with --user

python3 -m pip freeze --path /usr/local/lib/python$PYV/dist-packages > ~/sudo-pip.txt
sudo python3 -m pip uninstall --break-system-packages -y -r ~/sudo-pip.txt
mv ~/.local/lib/python$PYV ~/.local/lib/python$PYV.bak   # reversible

dpkg -S EXTERNALLY-MANAGED                   # which package owns the marker
sudo apt install --reinstall python3-yaml    # repeat for each damaged python3-* package
dpkg --verify python3-yaml                   # no output means the files match

If the marker was deleted, reinstall the package that dpkg -S names; if it was diverted, run sudo dpkg-divert --rename --remove followed by the marker's path. Then install the saved list into the venvs of the projects that need it.

Related errors​

  • "ensurepip is not available" when creating a venv: install the package the message names (python3-venv or a versioned one such as python3.12-venv), delete the half-built .venv and create it again.
  • "No module named venv": you are probably calling Python 2 or a stripped-down interpreter. Check python3 --version; on Debian and Ubuntu, python3-full brings the complete standard library.
  • pip: command not found: normal on a fresh Debian or Ubuntu system, because the pip command comes from the separate python3-pip package. You don't need it for venv work: inside an activated venv, pip is there.
  • pip and python disagree: pip --version shows which interpreter it belongs to; python -m pip always matches the python you call.
  • Activation does nothing: bash .venv/bin/activate runs in a separate shell process that exits at once. Use source; in bash, hash -r clears a cached command path.
  • The venv broke after an OS upgrade (bad interpreter, No such file or directory): its base Python was replaced. Delete .venv and rebuild it from requirements.txt; for pipx, run pipx reinstall-all.

FAQ​

Is this a bug in my system?
No. Debian, Ubuntu, Raspberry Pi OS, Homebrew and others enable it deliberately so that pip and the system package manager don't overwrite each other's files.

Can't I just pass --break-system-packages?
You can, but keep it for disposable systems. On a server you maintain, it trades a one-minute fix today for a hard-to-trace failure later.

Do I need a separate venv for every project?
Yes: one .venv and one requirements.txt per project, so upgrading one project can't break another.

pipx or uv tool?
Both install command-line apps into isolated environments. pipx is packaged by most distributions and is a safe default; uv tool is faster if you already use uv.

Does this affect Windows?
Not with the python.org installer, whose interpreter isn't marked. Inside WSL it does: an Ubuntu 24.04 distribution under WSL uses Ubuntu's own, marked Python. The venv workflow is the same in both places and still the cleanest way to keep projects apart.

Conclusion and next steps​

The error is the operating system asking you to keep your packages away from its Python. Match the tool to the job: venv for project libraries, pipx or uv tool for command-line apps, apt for libraries the distribution ships, and the official python image or a venv in containers. Next, create a .venv for your current project, save a requirements.txt, and point cron entries and systemd units at .venv/bin/python by its full path. If you need a server to run Python services on, AIOR's VPS hosting is one option. Questions about a specific setup are welcome in this thread.
 

Forum istatistikleri

Konular
925
Mesajlar
932
Üyeler
26
En son üye
Jessicawatson

Çevrimiçi üyeler

Şu anda çevrimiçi üye yok.

Öne çıkan içerik

AIOR
AIOR TEKNOLOJİ

Tüm ihtiyaçlarınız için Teklif alın

Hosting · Domain · Sunucu · Tasarım · Yazılım · Mühendislik · Sektörel Çözümler

Teklif al

7/24 Destek · Anında yanıt

Geri
Üst