12. Virtuelle Umgebungen und Pakete
***********************************


12.1. Einführung
================

Python-Anwendungen verwenden häufig Pakete und Module, die nicht Teil
der Standardbibliothek sind. Manchmal benötigen Anwendungen eine
bestimmte Version einer Bibliothek, da entweder ein bestimmter Fehler
behoben sein muss oder die Anwendung unter Verwendung einer veralteten
Version der Bibliotheksschnittstelle geschrieben wurde.

Das bedeutet, dass es unter Umständen nicht möglich ist, mit einer
einzigen Python-Installation die Anforderungen aller Anwendungen zu
erfüllen. Wenn Anwendung A die Version 1.0 eines bestimmten Moduls
benötigt, Anwendung B jedoch die Version 2.0, stehen die Anforderungen
im Konflikt miteinander, und die Installation entweder von Version 1.0
oder 2.0 führt dazu, dass eine der Anwendungen nicht ausgeführt werden
kann.

Die Lösung für dieses Problem besteht darin, eine *virtuelle Umgebung*
anzulegen – einen in sich geschlossenen Verzeichnisbaum, der eine
Python-Installation für eine bestimmte Python-Version sowie eine Reihe
zusätzlicher Pakete enthält.

Verschiedene Anwendungen können dann unterschiedliche virtuelle
Umgebungen nutzen. Um das zuvor genannte Beispiel widersprüchlicher
Anforderungen zu lösen, kann Anwendung A über eine eigene virtuelle
Umgebung verfügen, in der Version 1.0 installiert ist, während
Anwendung B eine andere virtuelle Umgebung mit Version 2.0 nutzt. Wenn
für Anwendung B ein Upgrade einer Bibliothek auf Version 3.0
erforderlich ist, hat dies keine Auswirkungen auf die Umgebung von
Anwendung A.


12.2. Erstellung virtueller Umgebungen
======================================

Das Modul zum Erstellen und Verwalten virtueller Umgebungen heißt
"venv" . Mit dem Befehl "venv" wird die Python-Version installiert,
von der aus der Befehl ausgeführt wurde (wie durch die Option  "--
version" angegeben). Wenn du den Befehl beispielsweise mit
"python3.12" ausführst, wird Version 3.12 installiert.

Um eine virtuelle Umgebung zu erstellen, lege ein Verzeichnis fest, in
dem du diese ablegen möchtest, und führe das Modul "venv" als Skript
mit dem Verzeichnispfad aus:

   python -m venv tutorial-env

Dadurch wird das Verzeichnis "tutorial-env" angelegt, falls es noch
nicht existiert, und es werden darin Unterverzeichnisse erstellt, die
eine Kopie des Python-Interpreters sowie verschiedene Hilfsdateien
enthalten.

Ein gängiger Speicherort für eine virtuelle Umgebung ist ".venv" .
Durch diesen Namen bleibt das Verzeichnis in der Regel in Ihrer Shell
verborgen und stört somit nicht, während der Name gleichzeitig
verdeutlicht, wozu das Verzeichnis dient. Außerdem wird dadurch eine
Kollision mit den Definitionsdateien der Umgebungsvariablen ".env"
vermieden, die von einigen Tools unterstützt werden.

Sobald du eine virtuelle Umgebung erstellt hast, kannst du diese
aktivieren.

Führe unter Windows Folgendes aus:

   tutorial-env\Scripts\activate

Unter Unix oder macOS führe folgenden Befehl aus:

   source tutorial-env/bin/activate

(Dieses Skript wurde für die Bash-Shell geschrieben. Wenn du die
Shells **csh** oder **fish** verwendest, solltest du  stattdessen die
alternativen Skripte unter "activate.csh" und "activate.fish"
verwenden.)

Durch das Aktivieren der virtuellen Umgebung ändert sich die
Eingabeaufforderung deiner Shell so, dass angezeigt wird, welche
virtuelle Umgebung du gerade verwendest, und die Umgebung wird so
angepasst, dass du mit dem Befehl "python" genau diese Version und
Installation von Python aufrufst. Zum Beispiel:

   $ source ~/envs/tutorial-env/bin/activate
   (tutorial-env) $ python
   Python 3.5.1 (default, May  6 2016, 10:59:36)
     ...
   >>> import sys
   >>> sys.path
   ['', '/usr/local/lib/python35.zip', ...,
   '~/envs/tutorial-env/lib/python3.5/site-packages']
   >>>

Beachte, dass die aktivierte virtuelle Umgebung die Variable
"PYTHONPATH" in keiner Weise verändert. Dies kann zu unerwarteten
Ergebnissen führen, wenn der Pfad Verweise auf Code enthält, der mit
der von der virtuellen Umgebung verwendeten Python-Version nicht
kompatibel ist. Es empfiehlt sich, in Bash den Befehl "unset
PYTHONPATH" auszuführen oder den entsprechenden Befehl für die von dir
verwendeten Shell.

Um eine virtuelle Umgebung zu deaktivieren, gebe Folgendes ein:

   deactivate

in das Terminal.


12.3. Pakete mit pip verwalten
==============================

Mit dem Programm **pip** kannst du Pakete installieren, aktualisieren
und entfernen. Standardmäßig installiert "pip" Pakete aus dem "Python
Package Index" ( <https://pypi.org>_). Du kannst den Python Package
Index durchsuchen, indem du die entsprechende Seite in deinem
Webbrowser aufrufst.

"pip" verfügt über eine Reihe von Unterbefehlen: "install",
"uninstall", "freeze" usw. (Die vollständige Dokumentation zu "pip"
findest du im Handbuch Installieren von Python-Modulen .)

Du kannst die neueste Version eines Pakets installieren, indem du den
Namen des Pakets angibst:

   (tutorial-env) $ python -m pip install novas
   Collecting novas
     Downloading novas-3.1.1.3.tar.gz (136kB)
   Installing collected packages: novas
     Running setup.py install for novas
   Successfully installed novas-3.1.1.3

Du kannst auch eine bestimmte Version eines Pakets installieren, indem
du den Paketnamen gefolgt von "==" und der Versionsnummer angibst:

   (tutorial-env) $ python -m pip install requests==2.6.0
   Collecting requests==2.6.0
     Using cached requests-2.6.0-py2.py3-none-any.whl
   Installing collected packages: requests
   Successfully installed requests-2.6.0

Wenn du diesen Befehl erneut ausführst, erkennt "pip" , dass die
angeforderte Version bereits installiert ist, und führt keine Aktion
durch. Du kannst eine andere Versionsnummer angeben, um diese Version
zu erhalten, oder du kannst "python -m pip install --upgrade"
ausführen, um das Paket auf die neueste Version zu aktualisieren:

   (tutorial-env) $ python -m pip install --upgrade requests
   Collecting requests
   Installing collected packages: requests
     Found existing installation: requests 2.6.0
       Uninstalling requests-2.6.0:
         Successfully uninstalled requests-2.6.0
   Successfully installed requests-2.7.0

"python -m pip uninstall" gefolgt von einem oder mehrere Paketnamen
entfernt die Pakete aus der virtuellen Umgebung».

"python -m pip show" zeigt Informationen zu einem bestimmten Paket an:

   (tutorial-env) $ python -m pip show requests
   ---
   Metadata-Version: 2.0
   Name: requests
   Version: 2.7.0
   Summary: Python HTTP for Humans.
   Home-page: http://python-requests.org
   Author: Kenneth Reitz
   Author-email: me@kennethreitz.com
   License: Apache 2.0
   Location: /Users/akuchling/envs/tutorial-env/lib/python3.4/site-packages
   Requires:

"python -m pip list" zeigt alle in der virtuellen Umgebung
installierten Pakete an:

   (tutorial-env) $ python -m pip list
   novas (3.1.1.3)
   numpy (1.9.2)
   pip (7.0.3)
   requests (2.7.0)
   setuptools (16.0)

"python -m pip freeze" gibt eine ähnliche Liste der installierten
Pakete aus, allerdings im Format, das "python -m pip install"
erwartet. Es ist üblich, diese Liste in einer Datei namens
"requirements.txt" abzulegen:

   (tutorial-env) $ python -m pip freeze > requirements.txt
   (tutorial-env) $ cat requirements.txt
   novas==3.1.1.3
   numpy==1.9.2
   requests==2.7.0

Die "requirements.txt" kann anschließend in die Versionskontrolle
übernommen und als Teil einer Anwendung ausgeliefert werden. Benutzer
können dann alle erforderlichen Pakete mit dem Befehl "install -r"
installieren:

   (tutorial-env) $ python -m pip install -r requirements.txt
   Collecting novas==3.1.1.3 (from -r requirements.txt (line 1))
     ...
   Collecting numpy==1.9.2 (from -r requirements.txt (line 2))
     ...
   Collecting requests==2.7.0 (from -r requirements.txt (line 3))
     ...
   Installing collected packages: novas, numpy, requests
     Running setup.py install for novas
   Successfully installed novas-3.1.1.3 numpy-1.9.2 requests-2.7.0

"pip" bietet viele weitere Optionen. Die vollständige Dokumentation zu
"pip" findest du im Handbuch Installieren von Python-Modulen . Wenn du
ein Paket erstellt hast und es im Python Package Index veröffentlichen
möchtest, lese bitte das Python Packaging User Guide.
