Virtual environments in Python erstellen

In diesem Betriag erkläre ich das Erstellen von virtual environments in Python und welche Vorteile diese mit sich bringen.

Anlegen von virtual environments in Python

Eine neue virtuelle Umgebung erstellt man mit Python entweder über virtualenv (für Python 2.x und auch Python3.x) oder über das seit Python3.3 vorhandene venv Modul.

    christian@ubuntu:~$ python3 -m pip install --user virtualenv

    christian@ubuntu:~$ virtualenv venv2.7 -p python2.7
    Running virtualenv with interpreter /usr/bin/python2.7
    Already using interpreter /usr/bin/python2.7
    New python executable in /home/christian/venv2.7/bin/python2.7
    Also creating executable in /home/christian/venv2.7/bin/python
    Installing setuptools, pip, wheel...
    done.

    christian@ubuntu:~$ virtualenv venv
    Using base prefix '/usr'
    New python executable in /home/christian/venv/bin/python3.6
    Also creating executable in /home/christian/venv/bin/python
    Installing setuptools, pip, wheel...
    done.

    christian@ubuntu:~$ python3.8 -m venv my_venv    

Aktivieren einer virtuellen Umgebung

Um eine virtuelle Umgebung zu aktivieren, benutzt man den ’source‘ oder ‚.‘ Befehl. Anschließend sieht man in der Console auch den in Klammern eingefassten Namen der aktiven Umgebung, wie z.B. (venv2.7).

‚deactivate‘ verlässt die virtuelle Umgebung wieder und man arbeitet anschließend mit der systemweit installierten Python Umgebung weiter.

    christian@ubuntu:~$ source venv2.7/bin/activate
    (venv2.7) christian@ubuntu:~$ python
    Python 2.7.17 (default, Jul 20 2020, 15:37:01)
    [GCC 7.5.0] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>>
    (venv2.7) christian@ubuntu:~$ deactivate
    christian@ubuntu:~$

    christian@ubuntu:~$ . venv/bin/activate
    (venv) christian@ubuntu:~$ python
    Python 3.6.9 (default, Jul 17 2020, 12:50:27)
    [GCC 8.4.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>>

Warum eine virtuelle Umgebung benutzt werden sollte

Eine virtuelle Umgebung zu erstellen, vereinfacht viele Dinge. Zum einen ist es möglich eine Umgebung für jede Python Version zu erstellen. Den Code testet man dann jeweils mit dem Interpreter dieser Umgebungen. Auch kann man verschiedene Umgebungen benutzen um unterschiedliche Python Bibliotheken zu installieren und das Zusammenspiel zu prüfen.

christian@ubuntu:~$ . venv2.7/bin/activate
    (venv2.7) christian@ubuntu:~$ pip install PyYAML
    DEPRECATION: Python 2.7 reached the end of its life on January 1st, ...
    Processing ./.cache/pip/wheels/d1/d5/a0/3c27cdc8b0209c5fc1385afeee936cf8a71e13d885388b4be2/PyYAML-5.3.1-cp27-cp27mu-linux_x86_64.whl
    Installing collected packages: PyYAML
    Successfully installed PyYAML-5.3.1

    (venv2.7) christian@ubuntu:~$ pip freeze
    DEPRECATION: Python 2.7 reached the end of its life on January 1st, ...
    PyYAML==5.3.1

    (venv) christian@ubuntu:~$ pip install PyYAML
    Collecting PyYAML
      Using cached PyYAML-5.3.1.tar.gz (269 kB)
    Building wheels for collected packages: PyYAML
      Building wheel for PyYAML (setup.py) ... done
      Created wheel for PyYAML: filename=PyYAML-5.3.1-cp36-cp36m-linux_x86_64.whl size=44619 sha256=0f1ed03590c156a3a40a55fd371aeb033da6e9ed24e68240133f1f704dfdd2a3
      Stored in directory: /home/christian/.cache/pip/wheels/e5/9d/ad/2ee53cf262cba1ffd8afe1487eef788ea3f260b7e6232a80fc
    Successfully built PyYAML
    Installing collected packages: PyYAML
    Successfully installed PyYAML-5.3.1

    (venv) christian@ubuntu:~$ pip freeze
    PyYAML==5.3.1

Python Scripte können mit dem Python Interpreter der aktivieren virtuellen Umgebung ausgeführt werden. Dadurch erhält das Script automatisch alle in der virtuellen Umgebung vorhandenen Python Bibliotheken.

Das kleine Test Script:

import yaml


def main():
    print("imported pyyaml")


if __name__ == "__main__":
    main()

wird einmal mit dem Interpreter von Umgebung A (PyYAML installiert) und Umgebung C (ohne PyYAML) ausgeführt:

christian@ubuntu:~/PycharmProjects/einfachpython/src/einfachpython$ source ~/ProjectA/venv_A/bin/activate
(venv_A) christian@ubuntu:~/PycharmProjects/einfachpython/src/einfachpython$ python script_with_pyyaml.py 
imported pyyaml

(venv_A) christian@ubuntu:~/PycharmProjects/einfachpython/src/einfachpython$ deactivate 

christian@ubuntu:~/PycharmProjects/einfachpython/src/einfachpython$ source ~/ProjectC/venv_C/bin/activate
(venv_C) christian@ubuntu:~/PycharmProjects/einfachpython/src/einfachpython$ python script_with_pyyaml.py 
Traceback (most recent call last):
  File "script_with_pyyaml.py", line 1, in <module>
    import yaml
ModuleNotFoundError: No module named 'yaml'
(venv_C) christian@ubuntu:~/PycharmProjects/einfachpython/src/einfachpython$ 

Beispiel von virtuellen Umgebungen in unterschiedlichen Projekten

Am wichtigsten ist jedoch, dass für jedes Projekt, welches man bearbeitet, eine eigene virtuelle Umgebung existiert. Für Projekt A installiert man nun Bibliothek PyYAML in Version 5.1, in Projekt B installiert man jedoch andere Bibliotheken. Vielleicht ergibt es sich dann, dass auch Projekt B die PyYAML Bibliothek benötigt, jedoch in einer neueren Version 5.3.1. Also wird nun gefahrlos PyYAML in die Umgebung von Projekt B installiert. Die Umgebung von Projek A bleibt davon unberührt und benutzt weiterhin Bibliothek PyYAML 5.1

Auf diesem Weg vermeidet man also Abhängigkeiten zwischen Projekten. Wäre z.B. alles in der systemweiten Umgebung installiert, müsste man je nach Projekt, das gerade bearbeitet wird, PyYAML up- oder downgraden, um die erforderliche Version zu benutzen.

    christian@ubuntu:~$ mkdir ProjectA
    christian@ubuntu:~$ cd ProjectA/
    christian@ubuntu:~/ProjectA$ python3.8 -m venv venv_A
    christian@ubuntu:~/ProjectA$ . venv_A/bin/activate
    (venv_A) christian@ubuntu:~/ProjectA$ pip install PyYAML==5.1
    Successfully installed PyYAML-5.1
    (venv_A) christian@ubuntu:~/ProjectA$ pip freeze
    PyYAML==5.1
    (venv_A) christian@ubuntu:~/ProjectA$ deactivate
    christian@ubuntu:~/ProjectA$ cd ..

    christian@ubuntu:~$ mkdir ProjectB
    christian@ubuntu:~$ cd ProjectB
    christian@ubuntu:~/ProjectB$ python3.8 -m venv venv_B
    christian@ubuntu:~/ProjectB$ . venv_B/bin/activate
    (venv_B) christian@ubuntu:~/ProjectB$ pip install PyYAML
    Successfully installed PyYAML-5.3.1
    (venv_B) christian@ubuntu:~/ProjectB$ pip freeze
    PyYAML==5.3.1
    (venv_B) christian@ubuntu:~/ProjectB$
    (venv_B) christian@ubuntu:~/ProjectB$ deactivate
    christian@ubuntu:~/ProjectB$ cd ..
    christian@ubuntu:~$ . ProjectA/venv_A/bin/activate
    (venv_A) christian@ubuntu:~$ pip freeze
    PyYAML==5.1

Bibliotheken festlegen und automatisch mit pip installieren

Um für ein Projekt eine für alle Entwickler gleiche Arbeitsumgebung schaffen zu können, benutzt man eine Datei, in der die Bibliotheken definiert sind. Solche requirements Dateien übergibt man mit dem -r Parameter dem install Kommando. Pip installiert dann die dort enhaltenen Pakete selbständig.

Für unser Projekt A erstellen wir uns also eine requirements.txt und legen dort fest, dass wir PyYAML in Version 5.1 benötigen. Ähnlich gehen wir für Projekt B vor, installieren dort aber die aktuellste Version von PyYAML (geben also keine feste Version an).

    christian@ubuntu:~$ . ProjectA/venv_A/bin/activate
    (venv_A) christian@ubuntu:~$ cat ProjectA/requirements.txt
    PyYAML==5.1
    (venv_A) christian@ubuntu:~$ pip install -r ProjectA/requirements.txt
    Successfully installed PyYAML-5.1
    (venv_A) christian@ubuntu:~$ pip freeze
    PyYAML==5.1
    (venv_A) christian@ubuntu:~$ deactivate

    christian@ubuntu:~$ . ProjectB/venv_B/bin/activate
    (venv_B) christian@ubuntu:~$ cat ProjectB/requirements.txt
    PyYAML
    (venv_B) christian@ubuntu:~$ pip install -r ProjectB/requirements.txt
    Successfully installed PyYAML-5.3.1
    (venv_B) christian@ubuntu:~$ pip freeze
    PyYAML==5.3.1

Löschen einer virtuellen Umgebung

Eine virtuelle Umgebung entfernt man einfach durch das Löschen des entsprechenden Verzeichnisses. Vorher deaktiviert man besser die Umgebung.

(venv_A) christian@ubuntu:~$ deactivate
christian@ubuntu:~$ rm -rf ProjectA/venv_A/

Weiterführende Lösungen zum Management von Bibliotheken

Neben dem eher manuellen pip/virtualenv gibt es weitere Lösungen virtuelle Umgebungen zu verwalten. Auch mit pipenv oder conda (im wissenschaftlichen Bereich) erstellt man virtuelle Umgebungen.

tl;dr

Virtuelle Umgebungen erzeugt man mit Python pip (und virtualenv für Py2) und separiert so die Interpreter für unterschiedliche Projekte. Bibliotheken verwaltet man damit für jedes Projekt unabhängig voneinander.

https://github.com/Sprungwunder/einfachpython/blob/master/src/einfachpython/virtualenv_example

Weiterführende Links (in englisch)

https://pypi.org/project/pip/

https://packaging.python.org/guides/installing-using-pip-and-virtual-environments/