Ich wollte auf meinem Debian-Server ein Python-Skript für Immich vorbereiten. Die benötigten Pakete standen in einer requirements.txt. Also erst einmal der übliche Befehl:
pip3 install -r requirements.txtStatt einer Installation kam diese Meldung:
error: externally-managed-environment
× This environment is externally managedDa fragt man sich schon, warum eine einfache Paketinstallation plötzlich nicht funktioniert. Die Meldung enthält allerdings bereits den Hinweis auf den passenden Weg: eine virtuelle Python-Umgebung.
Warum Debian die Installation blockiert
Das Python auf meinem Server wird über APT verwaltet. Wenn Pip dort ebenfalls Pakete installiert oder vorhandene Versionen ersetzt, können sich die beiden Paketverwaltungen gegenseitig in die Quere kommen. Programme des Betriebssystems erwarten möglicherweise andere Versionen als mein Skript.
Der Schutz ist unter dem Namen PEP 668 beschrieben. „Externally managed“ bedeutet hier also: Diese Python-Installation wird von der Distribution verwaltet. Für zusätzliche Projektpakete soll ich eine eigene Umgebung verwenden.
Mit --break-system-packages lässt sich die Sperre umgehen. Für dieses Skript sehe ich dafür aber keinen Grund. Auch sudo pip install ist keine sinnvolle Reparatur: Mehr Rechte lösen den Konflikt zwischen den Paketverwaltungen nicht.
Eine Umgebung für das Projekt anlegen
Zunächst installiere ich die Unterstützung für virtuelle Umgebungen:
sudo apt update
sudo apt install python3-venvDanach wechsle ich in den Ordner, in dem das Skript und die requirements.txt liegen. Der folgende Pfad ist ein Beispiel und muss zum eigenen Projekt passen:
cd /home/lars/immich-skripte
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txtAb dem Anlegen der Umgebung arbeite ich als normaler Benutzer in einem Ordner, auf den ich Schreibzugriff habe. Die zusätzlichen Pakete landen in .venv. Für ihre Installation ist kein sudo nötig.
Mit diesem Befehl kann ich den verwendeten Interpreter kontrollieren:
python -c "import sys; print(sys.executable)"Der ausgegebene Pfad sollte auf .venv/bin/python im Projektordner zeigen. Anschließend lässt sich das Skript starten:
python mein_skript.pymein_skript.py steht hier für den tatsächlichen Dateinamen. Mit deactivate verlasse ich die Umgebung wieder.
Für Cronjobs den richtigen Python-Pfad verwenden
Eine häufige Stolperfalle: Im Terminal läuft das Skript, später über Cron fehlen plötzlich Module. Die Aktivierung galt nur für die betreffende Shell. Ein Cronjob übernimmt sie nicht automatisch.
Deshalb verwende ich dort direkt den vollständigen Interpreterpfad. Eine Aktivierung ist dann nicht erforderlich:
/home/lars/immich-skripte/.venv/bin/python /home/lars/immich-skripte/mein_skript.pyDas Arbeitsverzeichnis muss trotzdem stimmen. Liest das Skript etwa eine Konfigurationsdatei über einen relativen Pfad ein, würde ich für Cron zusätzlich in den Projektordner wechseln. Bei einem systemd-Dienst gehört der Interpreterpfad in ExecStart und der Projektordner in WorkingDirectory.
Was damit gelöst ist
Die virtuelle Umgebung trennt die Python-Abhängigkeiten meines Skripts vom System-Python. Sie ersetzt keine Prüfung des Skripts selbst. Ein falscher Immich-Importpfad oder fehlende Leserechte auf Fotos bleiben separate Probleme.
Gerade bei meiner Bildersammlung möchte ich nach der Installation zunächst einen Probelauf nutzen, sofern das jeweilige Skript ihn unterstützt. Dass die Pakete installiert sind, ist noch keine Freigabe zum Ändern der Originaldateien.
Bei Downloads gibt es außerdem Programme außerhalb von Python, etwa FFmpeg oder aria2. Wie diese im Nextcloud-AIO-Setup bereitgestellt werden, habe ich im Beitrag MediaFetch mit Nextcloud AIO: yt-dlp, aria2 und FFmpeg dauerhaft installieren beschrieben.
Quellen: PEP 668 und die Python-Dokumentation zu venv.

Gedanken dazu 0 Kommentare
Noch ist es ruhig hier. Dein Gedanke könnte der erste sein.
Du kannst den Link auch in der Suche deiner eigenen Instanz öffnen. Öffentliche Antworten und bei Sharkey auch Home-Antworten können hier als Kommentare erscheinen. Antworten anderer Personen erscheinen nach Freigabe, deine eigenen direkt nach dem Abruf. Antworten nur für Follower werden nicht übernommen.
Was denkst du dazu?
Dein Kommentar erscheint nach der Freigabe.