Arbeiten in virtuellen Python-Umgebungen, Teil 1 Venv als Testumgebung für Python

Von Mirco Lang 6 min Lesedauer

Der Einstieg ins Python-Coding läuft meist beschaulich: Ein Terminal, das System-Python und der Paketmanager Pip – und es kann losgehen, ganz ohne komplexe Entwicklungsumgebung. Die ersten Probleme lassen allerdings dennoch selten lange auf sich warten.

Für das Testen von Python-Code bieten sich virtuelle Umgebungen an.(Bild:  Johnson Martin /  Pixabay)
Für das Testen von Python-Code bieten sich virtuelle Umgebungen an.

Nicht selten fangen die Probleme bei der Entwicklung mit Python an, wenn die ersten eigenen Projekte von Dritten getestet werden sollen. Schnell heißt es dann, diese oder jene Funktion sei nicht vorhanden, Bibliothek XY würde fehlen und so weiter.

Entwicklungsprojekte hängen nahezu immer von externen Tools ab und die Abhängigkeiten müssen nicht einfach nur vorhanden sein, sondern in der exakt richtigen Version. Schon kleine Änderungen führen schnell zu Fehlern, wenn zum Beispiel eine Funktion umbenannt wird oder sich auch nur Formate für Parameter ändern.

Spätestens wenn auf dem Rechner nun nicht nur ein einziges Projekt läuft, fangen die Probleme an. Was, wenn Projekt A eine Bibliothek in Version 1.0 und Projekt B dieselbe Bibliothek in Version 1.5 benötigt? Oder gar unterschiedliche Python-Versionen im Einsatz sind? Natürlich könnte man hier mit virtuellen Maschinen oder schlanken Containern zu Werke gehen, aber so lange keine komplett unterschiedliche konfigurierte Betriebssysteme benötigt werden, ist das zu umständlich.

Die Lösung sind virtuelle Umgebungen. Diese lassen sich im Terminal oder auch in einer integrierten Entwicklungsumgebung (IDE) ganz fix aufbauen, mit eigenen Python-Programmen und dann bei Bedarf aktivieren. Auch können ein Dutzend solcher Umgebungen parallel laufen, ohne dabei Ressource zu verschwenden.

Wenn Dritte testen sollen, liegt der Vorteil auf der Hand: der übliche Spruch „Auf meinem Rechner läuft es aber …“ wird obsolet. Eine identische Testumgebung lässt sich nämlich fix aufbauen. Mit einem etwas außergewöhnlichen Tool lässt sich die gesamte Umgebung portabel aufbauen und als Paket weitergeben. Aber kommen wir erst einmal zu den Basics.

venv-Modul

Die wesentlichen Voraussetzungen für virtuelle Umgebungen sind Python selbst sowie das venv-Modul und der Paketmanager Pip. In der Regel bringen Python-Installationen die beiden Tools direkt mit, in einigen Fällen wie unter Ubuntu muss man Pip manuell nachinstallieren.

Vorab: Der Einfachheit halber heißt es im Folgenden immer nur „python“ statt „python3“, wie es auf manchen Systemen heißen müsste. Der Aufbau einer virtuellen Umgebung ist denkbar einfach:

python -m venv .venv

Bei diesem Standardaufruf führt Python das venv-Modul aus, das einen versteckten Unterordner „.venv“ im aktuellen Verzeichnis erzeugt. Wichtig dabei: Auch wenn es sich fast immer genau so liest und nach fixer Syntax aussieht, ist .venv nur ein beliebiger Name – man könnte genauso gut „.myappenv“ verwenden. Nun, fast genauso gut – aber dazu später mehr. Sprechende Namen mögen vorteilhaft wirken, andererseits finden sich die venv-Ordner immer unterhalb der zugehörigen Projektordner.

Nun steht die virtuelle Umgebung zur Verfügung, sie muss aber zunächst aktiviert werden:

source .venv/Scripts/activate

Leider ist das nur eine Variante für die Aktivierung, in diesem Fall unter Windows in der Bash. Unter Linux ist es standardmäßig:

source .venv/bin/activate

Sowohl das „bin“- als auch das „Scripts“-Verzeichnis enthalten diverse ausführbare Dateien für unterschiedliche Shells, beispielsweise „activate.ps1“ oder „activate.fish“ – aktiviert wird aber über „activate“ ohne jegliche Endung.

Dass man sich in einer virtuellen Umgebung befindet, zeigt eine Erweiterung des Prompts, dem der Name des venv-Verzeichnisses, standardmäßig „(.venv)“, vorangestellt wird:

(.venv) nutzer@meincomputer

Dieses Präfix lässt sich aber auch direkt selbst festlegen:

python -m venv --prompt MeineUmgebung .venv
(MeineUmgebung) nutzer@meincomputer

Der Vorteil: venv-Ordner bleibt beim Standard „.venv“ und Sie haben dennoch einen hilfreichen Namen am Prompt. Und „.venv“ als Ordnername hat mindestens einen gravierenden Vorteil: IDEs wie zum Beispiel Visual Studio Code (VSC) erkennen und verarbeiten vorhandene virtuelle Python-Umgebungen – VSC aber eben nur dann, wenn der Ordner „.venv“ heißt.

Visual Studio Code erkennt vorhandene venv-Umgebungen.(Bild:  Lang / Microsoft)
Visual Studio Code erkennt vorhandene venv-Umgebungen.
(Bild: Lang / Microsoft)

Insofern lohnt es sich, hier beim Standard zu bleiben und stattdessen die prompt-Option zu nutzen (auch wenn man sie in Praxisbeispielen leider selten sieht). Natürlich nur, wenn es nur eine virtuelle Umgebung für diesen einen Projektordner gibt – Sie können auch .venv1 bis .venvN auf ein und dasselbe Projekt loslassen.

Wer noch sicherer sein will, in der venv-Umgebung zu sein:

where python

… listet in der Regel zumindest zwei Python-Versionen: Das System-Python und das venv-Python. Um sicher zu gehen, dass auch das richtige Python genutzt wird:

Jetzt Newsletter abonnieren

Täglich die wichtigsten Infos zur IT-Sicherheit

Mit Klick auf „Newsletter abonnieren“ erkläre ich mich mit der Verarbeitung und Nutzung meiner Daten gemäß Einwilligungserklärung (bitte aufklappen für Details) einverstanden und akzeptiere die Nutzungsbedingungen. Weitere Informationen finde ich in unserer Datenschutzerklärung. Die Einwilligungserklärung bezieht sich u. a. auf die Zusendung von redaktionellen Newslettern per E-Mail und auf den Datenabgleich zu Marketingzwecken mit ausgewählten Werbepartnern (z. B. LinkedIn, Google, Meta).

Aufklappen für Details zu Ihrer Einwilligung
which python

… gibt den Pfad zur genutzten Python-Executable zurück:

/c/Users/Nutzer/projekte/app1/.venv/Scripts/python

Wenn das so weit funktioniert, lässt sich die aktive Umgebung produktiv nutzen, sprich Software installieren, etwa:

pip install cowsay

Wieder ist ein Blick in den .venv-Ordner interssant: Unter „.venv/Lib/site-packages“ finden sich die installierten Pakete und unter „.venv/Scripts“ die ausführbaren Dateien, hier also zum Beispiel „cowsay.exe“.

Um nun alle in der Umgebung eingerichteten Pakete anzuzeigen, bietet sich …

pip list

… an, das hübsch und menschenfreundlich formatiert ausgibt. Wesentlich nützlicher ist jedoch:

pip freeze > requirements.tx

Auch „freeze“ gibt die Pakete und Versionen aus, allerdings im Requirements-Format (etwa foobar==1.1.4). Und über die Requirements-Datei lässt sich die virtuelle Umgebung dann bei Dritten oder auf weiteren Testmaschinen ausrollen.

Zu guter Letzt: Um die Umgebung zu verlassen genügt ein simples …

deactivate

… ohne Angabe des Pfads – schließlich ist das Verzeichnis zu „/Scripts“ beziehungsweise „/bin“ innerhalb der virtuellen Umgebung im Systempfad. Eine spezielle Funktion zum Löschen gibt es nicht, hier tut es das übliche „rm -r“.

Die Weitergabe an Dritte über die Requirements-Datei ist sicherlich einer der schönsten Aspekte des venv-Konzepts. Allerdings geht es noch etwas portabler – mit dem Nischen-Tool RCC.

Portable Umgebung

Beim Verteilen mittels Requirements-Datei werden auf dem Zielrechner immer noch Python und Pip vorausgesetzt und auch dort könnte es schon zu Problemen mit Versionen kommen.

Eine interessante, wenn auch etwas abwegige Lösung bietet wie erwähnt RCC. Das quelloffene Kommandozeilen-Tool ist eigentlich nur für den Kontext Robot Framework, betrieben bei Robocorp, gedacht – erweist sich aber auch abseits davon als enorm nützlich.

Der Sinn von RCC ist es, portable „Robots“ zu handhaben, die ohne weitere Abhängigkeiten laufen und Automationen oder Tests ausführen. Und dafür nutzen sie deklarativ aufgebaute virtuelle Umgebungen.

Für eine portable RCC-Umgebung benötigen Sie drei Dateien: Die rcc-Binary, die Paketkonfiguration „robot.yaml“ und die Deklaration der Abhängigkeiten „conda.yaml“.

Die robot.yaml sieht standardmäßig folgendermaßen aus:

tasks:
  Run all tasks:
    shell: python -m robot --report NONE --outputdir output --logtitle "Task log" tests.robot
environmentConfigs:
  - environment_windows_amd64_freeze.yaml
  - environment_linux_amd64_freeze.yaml
  - environment_darwin_amd64_freeze.yaml
  - conda.yaml
artifactsDir: outputPATH:
  - .
PYTHONPATH:
  - .
ignoreFiles:
  - .gitignore

Für den Einsatz abseits von Automationen sind hier nur zwei Angaben unter „environmentConfigs“ relevant: Die „conda.yaml“ als Quelle für die virtuelle Umgebung und die Freeze-YAML für das jeweilige System. Die Freeze-Datei hält wie zu erwarten fest, welche Tools in welchen Versionen letztlich installiert wurden – kümmern müssen Sie sich darum nicht.

Spannender ist die conda.yaml, die zum Beispiel so aussehen kann:

channels:
  - conda-forge
dependencies:
  - python=3.10.12
  - pip=23.2.1
  - pip:
    - cowsay

Als Quelle für Pakete wird hier zunächst conda-forge angegeben – es wird also mit Conda gearbeitet? Nicht ganz, im Hintergrund werkelt Micromamba. Wer es nicht kennt: Micromamba ist eine Mini-Version von Mamba, was wiederum eine Re-Implementierung des Paketmanagers Conda in C++ ist.

In den Dependencies lassen sich neben conda-forge-Paketen aber auch pip-Pakete angeben, sofern Pip installiert wird. Dieses Paket aus rcc/rcc.exe, robot.yaml und conda.yaml wird dann in dieser Form verteilt. Auf dem Zielsystem wird nichts vorausgesetzt. In die Umgebung gelangt man mit dem Befehl

rcc.exe task shell

Der Aufbau der Umgebung dauert beim ersten Mal einige Zeit – später wird sie wiederverwendet, bis sich die conda.yaml wieder ändert. In der Shell bieten sich dann wieder Befehle wie …

where python

… an, was in diesem Fall ein Ergebnis dieser Art hervorbringt:

/c/Users/User/AppData/Local/robocorp/holotree/109dad2_5a1fac3_9fcd2534/python

Holotree gehört zu RCC und sorgt zum Beispiel dafür, dass beim Aufbau weiterer Umgebungen mit anderen Python-Versionen nur die Python-Bestandteile neu geladen werden, die auch wirklich unterschiedlich sind – der Rest wird wiederverwertet.

Zum Verlassen der Umgebung genügt ein:

exit

RCC ist freilich etwas klobiger als ein minimalistisches venv-Modul und ab und an begegnen einem Artefakte aus dem Robocorp-/Robot-Framework-Universum, dafür gibt es aber keine Voraussetzungen, vollständige Portabilität und Nutzer müssen keine Ahnung von venv haben.

(ID:50021699)