Python Tutorial Teil 2 - Paketmanagement

Teil 2: Paketmanagement dieses kompakten Python-Tutorials beschreibt, wie man mit Hilfe der Paketverwaltungssysteme pip und conda Python-Pakete installiert, aktualisiert und deinstalliert, wie man für verschiedene Projekte passende Anwendungsumgebungen ("environments") erstellt und wie man die installierten Pakete in Python-Skripten mit Hilfe der import-Anweisung korrekt importiert. Die Entwicklung selbstdefinierter Pakete, mit deren Hilfe man größere Projekte strukturieren kann, wird an einem Beispiel vorgestellt.

  Motivation

Zu den größten Stärken der Programmiersprache Python gehört der Umfang und die Benutzerfreundlichkeit kostenloser Bibliotheken für verschiedene Anwendungsgebiete, insbesondere auch Data Science, Machine Learning und Cyber Security.

Python-Bibliotheken verfügen nicht nur über eine umfangreiche Dokumentation und viele Beispiele, sondern auch über zwei leistungsstarke Paketverwaltungssysteme, pip und conda, die es einfach machen, Arbeitsumgebungen für verschiedene Aufgaben zu erstellen.

1 Was sind Python-Pakete?

Python-Pakete (packages) sind Klassen- und Funktionsbibliotheken, d.h. Gruppierungen von Klassen und Funktionen für definierte Einsatzgebiete. Ein Paket ist einfach ein Verzeichnis, das eine Datei __init__.py enthält, die leer sein kann, sowie eine beliebige Anzahl an Python-Modulen, die zusammengehörige Funktionen und Klassen gruppieren. Als Modul bezeichnet man in Python jede Python-Quelldatei, z.B. main.py oder decisiontree.py.

Nachdem ein Python-Paket erstellt wurde, können die darin definierten Klassen und Funktionen in anderen Python-Skripten verwendet werden, indem man entweder das komplette Paket oder nur einzelne Module oder Klassen / Funktionen importiert.

Python-Pakete kommen auf zweierlei Arten zum Einsatz: zum einen verwendet man Funktionen vorhandener Pakete, um gewisse Aufgaben durchzuführen. Zum anderen entwickelt man eigene Funktionen und Module für Teilaufgaben und strukturiert damit größere Programme.

Python verfügt über eine eingebaute Standardbibliothek (Python Standard Library), die direkt nach der Installation verfügbar sind, und viele grundlegende Funktionen schon enthält, wie z.B. mathematische Funktionen, Systemfunktionen, Dateizugriff, Verschlüsselung und andere häufig benötigte Aufgaben. Darüber hinaus gibt es eine Reihe von spezialisierten Python-Bibliotheken, die Funktionen für Datenanalyse, Machine Learning, Kryptografie und andere Anwendungen zur Verfügung stellen.

Eine aktuelle Liste der Python-Bibliotheken und -Software wird im Python Package Index (PyPI) verwaltet.

2 Python-Pakete installieren

Um ein spezielles Python-Paket verwenden zu können, muss es zuvor installiert werden.

Python-Bibliotheken, die nach der Installation nicht schon dabei sind, können über die Paketverwaltungstools pip und conda einfach hinzu installiert werden. Das Paket­verwaltungstool pip funktioniert nur mit Python-Modulen. Das Paket­verwaltungs­tool conda kann auch verwendet werden, um Module in anderen Programmiersprachen zu laden, z.B. in der statistischen Programmiersprache R. Weiterhin ermöglich das Paket­verwaltungs­tool conda das Erstellen und Verwalten von Umgebungen ("environments"), d.h. Verzeichnisse, in die man zueinander passende Versionen von Python und Python-Paketen inkl. Abhängigkeiten installieren kann.

Die beiden Tools pip und conda werden über Python-Konsole bzw. das Terminal bedient. Die Syntax der Befehle ist ähnlich, z.B. pip list (install, uninstall, ...) oder conda list (install, remove, ...).

2-1 Paketmanager pip

Pip ist das Standardpaketverwaltungssystem von Python. Die allgemeine Syntax eines Pip-Befehls lautet pip befehl paket optionen. Der Befehl ist einer von: list, show, install, uninstall. Die Optionen können auf zwei Arten angegeben werden: einerseits ausführlich, beispielsweise pip --help, oder in einer Kurzform, beispielsweise in pip -h.

Pakete mit pip verwalten
Dieses Beispiel zeigt, wie man pip verwendet, um Pakete aufzulisten, Informationen für ein bestimmtes Paket anzuzeigen und ein Paket zu installieren / aktualisieren / deinstallieren.

pip --help
pip list
pip show numpy, pandas
pip install pandas
pip install numpy --update
pip uninstall numpy

Größere Python-Projekte erfordern die Installation mehrerer Python-Pakete in passenden Versionen. Um diesen Prozess zu vereinfachen, werden die erforderlichen Abhängigkeiten für ein Projekt in eine Datei namens requirements.txt geschrieben, die mit der Option -r an den Befehl pip install übergeben wird. Die Option -r installiert alle Pakete, die in einer Datei requirements.txt aufgeführt sind.

Beispiel: Bibliotheken mit requirements.txt installieren
In diesem Beispiel werden alle für ein Reinforcement Learning-Projekt erforderlichen Bibliotheken mit der genauen Version in der Datei „requirements.txt“ angegeben und mithilfe von pip in einer dedizierten Conda-Umgebung installiert.

Schritt 1: Erstelle requirements.txt
Diese Datei sollte im Projektordner abgelegt werden.

# requirements.txt
tensorflow==2.12.0 
keras-rl2==1.0.5
gym==0.25.2

Schritt 2: Installiere mittels pip
Die nächsten Befehle werden im Terminal ausgeführt, hier Windows / cmd. Es ist wichtig, dass man zunächst mittels cd in das Projektverzeichnis wechselt, in dem sich die Datei requirements.txt befindet. Danach wird eine neue Conda-Umgebung mit dem Namen env-rl erstellt, aktiviert und die Bibliotheken werden mit pip in diese Umgebung installiert.

cd C:\users\ihrname\rl
conda create --name env-rl
conda activate env-rl
pip install -r requirements.txt


2-2 Paketmanager conda

Conda ist ein Paketverwaltungs-Programm, das zum Installieren und Aktualisieren von Paketen sowie zum Verwalten von Anwendungsumgebungen ("Environments") verwendet wird. Die allgemeine Syntax eines Conda-Befehls lautet conda befehl paket optionen.

Pakete mit Conda verwalten
Dieses Beispiel zeigt, wie man mit conda Pakete auflistet und ein Paket installiert / aktualisiert / deinstalliert.

conda list
conda install pandas 
conda install --name myenv pandas 
conda update pandas
conda remove pandas

Umgebungen mit Conda verwalten
Conda-Umgebungen sind Verzeichnisse, in die man zueinander passende Versionen von Python und Python-Paketen inkl. Abhängigkeiten installieren kann. Umgebungen können aktiviert und deaktiviert werden. Durch die Verwendung von Umgebungen können Anwendungen mit spezifischen Anforderungen parallel betrieben werden.

In diesem Beispiel erstellen wir eine Umgebung namens ML, aktivieren sie, installieren einen speziellen Satz von Programmpaketen darin und deaktivieren sie dann.

conda create --name ML
conda activate ML
conda install pandas tensorflow keras
conda deactivate ML

3 Python-Pakete importieren

Python-Bibliotheken und -Funktionen werden mit dem Befehl import importiert, gefolgt vom Namen der zu importierenden Bibliothek, zum Beispiel import numpy. Nach dem Import einer Bibliothek können alle ihre Klassen und Funktionen verwendet werden, indem der Name der Bibliothek dem Klassen- oder Funktionsnamen vorangestellt wird, wie in numpy.array oder numpy.linspace.

Beim Importieren von Paketen / Modulen / Klassen / Funktionen wird die Punkt-Notation verwendet, um die Zugehörigkeit zu kennzeichnen. z.B. paket.modul.klasse. Es können auch Alias-Namen für Pakete und Module vergeben werden, dies sind Kurznamen, die die Verwendung im Code vereinfachen. Valide Syntax ist z.B.
import paket as pk
import paket.modul as md
from paket.modul import klasse as kl


3-1 Importiere Pakete mittels Alias

Eine bewährte Methode für Importe besteht darin, einen abgekürzten Aliasnamen zu verwenden, z.B. np für NumPy oder plt für Matplotlib. Im folgenden Beispiel werden die Pakete NumPy und Matplotlib jeweils mit einem Aliasnamen importiert, der dann den Funktionsaufrufen vorangestellt werden muss, z.B. np.linspace() oder plt.plot().

import numpy as np  
import matplotlib.pyplot as plt
x = np.linspace(0,10,40)  # x-Werte
y = np.sin(x); # y-Werte
# Plot der Sinus-Funktion
plt.plot(x, y,'r*', label='sin');  

3-2 Importiere selektiv Klassen oder Funktionen

Mit der import-Anweisung können entweder ganze Pakete importiert werden, z.B. import numpy oder selektiv nur die benötigten Klassen / Funktionen aus Paketen, z.B. from numpy import linspace, sin. In diesem Beispiel importieren wir nur die benötigten Funktionen: linspace, lin und plot.

from numpy import linspace, sin
from matplotlib.pyplot import plot
x = linspace(0, 10, 40)
y = sin(x)
plot(x, y,'r*', label='sin');

3-3 Best practices

Die beste Vorgehensweise beim Importieren von Paketen besteht darin, möglichst explizite und eindeutige Angaben zu machen. Normalerweise bedeutet dies, das gesamte Paket unter Verwendung eines kurzen Aliasnamens zu importieren, z.B. np für Numpy und plt für Matplotlib, und diesen Alias ​​jedem Klassen- und Funktionsaufruf voranzustellen. Dadurch wird sichergestellt, dass der Code transparent ist und klar wird, welche Funktion zu welchem ​​Paket gehört, auch wenn die Funktionsaufrufe etwas länger werden. Wenn man mit bestimmten Klassen in einer tieferen Hierarchie arbeitet, kann es praktischer sein, diese einzelne Klasse zu importieren. Zum Beispiel wird beim Verwenden der Unterklassen und Methoden des Moduls tree aus der Scikit-Learn-Bibliothek zunächst das Modul tree importiert und dann auf seine Unterklassen und Methoden zugegriffen, indem man allen Aufrufen den Namen des Moduls (hier: tree) voranstellt.

from sklearn import tree
model = tree.DecisionTreeClassifier(criterion='entropy', splitter='best')
model.fit(X_train, y_train)
tree.plot_tree(model)

4 Selbstdefinierte Python-Pakete

Um ein eigenes Python-Paket zu erstellen, müssen lediglich alle zusammengehörigen Python-Quelldateien in ein eigenes Verzeichnis abgelegt werden, und in diesem Verzeichnis muss zwingend auch eine Datei mit dem Namen __init.py__ vorhanden sein. Der Inhalt der __init.py__ darf leer sein, diese Datei hat lediglich die Aufgabe, das Verzeichnis als Packet zu kennzeichnen.

4-1 Paket erstellen

Als Beispiel erstellen wir ein Package mit dem Namen mypkg, das zwei Module enthält, module1.py und module2.py. Das Modul module1.py enthält die Definition zweier Funktionen myfunc1 und myfunc2. Das Modul module2 enthält die Definition einer Klasse "Auto". Die Verzeichnisstruktur sieht wie abgebildet aus:

Paketverzeichnis mypkg
Paketverzeichnis mypkg
mypkg/module1.py
def my_func1(text):        
    print(text)
def my_func2(x):
  return x*2


mypkg/module2.py
class Auto:
  def __init__(self, herst, modell):
     self.herst = herst
     self.modell = modell
  def ausgeben(self):
     print("Hersteller: ...")

4-2 Paket verwenden

Um das zuvor erstellte Paket zu verwenden, erstellen wir ein Test-Skript pkg_test.py, das sich im übergeordneten Verzeichnis relativ zu dem Verzeichnis mypkg befindet. Wir importieren die Module module1 und module2 mit Alias-Namen m1 und m2.
Der Befehl import mypkg.module1 as m1 importiert das Modul module1 aus dem Paket mypkg mit dem Namen Alias-Namen m1. Dies bedeutet, dass die Funktionsaufrufe in der Form m1.myfunc1() angegeben werden müssen.

pkg_test.py
import mypkg.module1 as m1
m1.my_func1("Hallo!")
print(m1.my_func2(10))
import mypkg.module2 as m2
my_auto1 = m2.Auto("Audi", "A3") 
my_auto2 = m2.Auto("BMW", "i3")
my_auto1.ausgeben() # Ausgabe: Hersteller: Audi, Modell: A3
my_auto2.ausgeben() # Ausgabe: Hersteller: BMW, Modell: i3

Autoren, Tools und Quellen

Autor:
 Prof. Dr. Eva Maria Kiss


Tools:

elab2go-Links

Quellen und weiterführende Links