Python-Abhängigkeiten projektbezogen verwalten

Ich bin generell eher kein Python-Entwickler und kam irgendwann in die Situation, Python-Abhängigkeiten bei der Nutzung von AWS und unterschiedlichen CLI-Tools (aws-cli, eb-cli, etc.) zu verwalten. Jetzt kann man natürlich sagen: „Egal – installiert euch lokal-global das aktuellste aws/eb-cli und gut ist“.

Mir war es aber im Sinne der Professionalität wichtig, das auch projektbezogen und für eine Kollaboration reproduzierbar zu machen. Folgende Problemstellungen ergaben sich letztlich daraus:

  • Ich brauche Python möglicherweise in verschiedenen Versionen – gibt es sowas wie „nvm“ auch für Python?
  • Wie kann ich mit pip(3) installierte Abhängigkeiten reproduzierbar verwalten?

Lösungsansätze

Für beide Problemstellungen existiert jeweils eine praktische Lösung, die ich an dieser Stelle kurz vorstellen möchte.

Verschiedene Python-Versionen

Die Lösung des Problems heißt „virtualenv“. Das CLI-Tool bietet die Möglichkeit, isolierte Python-Umgebungen z. B. je Projekt mit gewünschter Python-Version zu erstellen. Die Installation läuft normalerweise über pip(3), viele Betriebssysteme bieten allerdings auch eigene Pakete für virtualenv an.

In meinem Fall (macOS), habe ich Python 3 via Homebrew installiert und als Standard-Python-Version für mein System gelinkt. Dort habe ich dann virtualenv via pip3 installiert. Das würde folgendermaßen funktionieren:

Um eine neue Python-Umgebung anzulegen, wird folgendes Kommando benutzt:

Die Angabe hinter dem Befehl steht für für den Namen des Ordners, in dem die neue Umgebung ihre Daten hält. Mit Hilfe des Parameters „-p“ kann die gewünschte Python-Binary – wenn sie im PATH liegt einfach so, andernfalls unter Angabe des kompletten Pfades – angegeben werden, um so eine Umgebung mit der benötigten Version zu erhalten. Standardmäßig wird die Python-Version genutzt, unter der virtualenv installiert ist.

Aktivieren der Umgebung

Anschließend muss die neue Umgebung aktiviert werden, womit natürlich auch möglicherweise global installierte Pakete „verloren“ gehen, d. h. dass sie nicht verfügbar sind:

Falls euch /.python_env/ als Ordner nicht zugesagt hat, müsste der Name natürlich entsprechend angepasst werden.

Wenn ihr mit der Arbeit an eurem Projekt fertig seid, könnt Ihr entweder das Terminal schließen bzw. einen neuen Tab nutzen oder mit dem Befehl deactivate, der nur innerhalb der virtualenv-Umgebung verfügbar ist, die Python-Umgebung verlassen.

Somit wäre das erste Problem gelöst. Kommen wir nun zum zweiten Teil:

Abhängigkeiten projektbezogen verwalten

Der Paketmanager pip(3) bringt hierfür die benötigte Funktion bereits mit: „freeze“. Dieses Kommando gibt die aktuell installierten Python-Pakete inklusive Version in einem lesbaren aber auch für pip verständlichen Format aus.

Allerdings sollte man eine Sache beachten: Bei der Nutzung von virtualenv unterscheidet sich die Ausgabe je nach aktiver Umgebung! Ist keine Umgebung aktiv, gibt pip die für die standardmäßig aktiven Python-Version installierten Pakete aus (Abb. 1 & Abb. 2).

Python-Abhängigkeiten ohne aktives pythonenv

Abb. 1: Beispiel 1 (ohne aktives pythonenv)

Python-Abhängigkeiten mit aktivem pythonenv

Abb. 2: Beispiel 2 (mit aktivem pythonenv)

Wie man sehen kann, sind das ganz schön viele Abhängigkeiten. Das liegt daran, das pip(3) in diesem Fall nicht nur die eigentlichen Abhängigkeiten auflistet, sondern auch die Abhängigkeiten derer, und so weiter …

Abhängigkeiten eingrenzen

Man hat nun zwei Möglichkeiten:

1. Nutzen von pip freeze > python_requirements.txt, um eine Art „Lock-Datei“ mit den Abhängigkeiten zu erstellen
2. Liste der Abhängigkeiten via pip freeze ausgeben lassen, diese dann manuell prüfen und entsprechend selbst eine Datei mit relevanten Abhängigkeiten erstellen

Wenn nun eine entsprechende Datei mit Abhängigkeiten existiert, können sie über den folgenden Befehl automatisch installiert werden:

Der Wert der Parameters „-r“ steht natürlich für die Datei, die entsprechend die Liste der Abhängigkeiten mit Version enthält.

Zusammenfassung

Um es mir selbst etwas leichter zu machen, habe ich mir inzwischen einen One-Liner gebastelt, den man sich gerne auch als Alias eintragen kann; Voraussetzung in meinem Fall wäre, das die Projekt-Struktur – /.python_env/ und python_requirements.txt – immer gleich sein müssen.

Für neue Blogupdates anmelden:


2 Gedanken zu “Python-Abhängigkeiten projektbezogen verwalten

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.