Python organisiert Sourcecode in Modulen. Ein Modul ist nichts anderes,
als eine Datei mit der Extension .py
.
Module dienen dazu,
Kleine Skripte kann man ohne weiteres in eine einzige Datei packen. Sobald ein Programm aber mehr als ein paar hundert Zeilen hat, empfiehlt es sich, den Code auf mehrere Module aufzuteilen, auch weil der Code dadurch einfacher zu pflegen und zu testen ist.
Damit ein Modul im eigenen Programm verwendet werden kann, muss das Modul zuerst importiert werden:
import <Modulname>
Danach steht das Modul mit der dort definierten Funktionalität zur Verfügung. Das in der mit Python mitinstallierten Standardlibrary vorhandene Modul random
stellt eine Reihe von Zufalls-Funktionen bereit. Damit wird diese verwenden können, müssen wir das Modul zuerst importieren:
In [ ]:
import random
Danach können wir uns beispielsweise eine Zufallszahl generieren lassen:
In [ ]:
random.randint(0, 1000000)
Im letzten Beispiel haben wir nicht irgendeine Funktion mit dem Namen randint
verwendet, sondern genau die, die vom Modul random
bereit gestellt wird.
Module strukturieren daher nicht nur den Sourcecode, sondern bilden auch Namensräume, wodurch verhindert wird, dass sich beispielsweise zwei in unterschiedlichen Modulen definierte, gleichnamige Funktionen gegenseitig überlagern. Um das zu verdeutlichen habe ich im Verzeichnis, in dem dieses Notebook liegt, zwei minimale Module angelegt:
In beiden Modulen gibt es eine Funktion serialize()
, die wir unter Nutzung der Namensräume beide in unserem Programm nutzen können:
In [ ]:
import a
import b
a.serialize()
b.serialize()
Der Namensraum ist einfach der Name der Datei, die das Modul repräsentiert.
Im obigen Beispiel gibt es also ein Modul (d.h. eine Datei) a.py
und ein
zweites Modul b.py
.
Wir haben bereits gehört, dass wir Module importieren müssen, ehe wir sie verwenden können. Dazu gibt es verschiedene Möglichkeiten. Die einfachste haben wir bereits kennengelernt: Wir importieren das gesamte Modul unter Beibehaltung des Modulnamens. Als Beispiel verwenden wir wieder ein Modul aus der Standard-Library: sys
stellt Informationen zur aktuellen Systemumgebung bereit:
In [ ]:
import sys
sys.version
In [ ]:
sys.platform
In [ ]:
from sys import platform
platform
Achtung: Hier haben wir etwas aus einem Modul in den globalen (bzw. unseren eigenen) Namensraum importiert. Wir ersparen uns dadurch zwar Tipparbeit, handeln uns aber auch einige Probleme ein, weil wir den eigenen Namensraum verschmutzt haben:
platform
auf sich hat - sys.platform
ist hier viel klarer.Hier ein Beispiel:
In [ ]:
version = '0.9 beta'
print('Sie verwenden MeinProgramm in Version {}'.format(version))
# Imports sollten immer ganz oben passieren, man kann sie aber überall verwenden
from sys import version
print('Sie verwenden MeinProgramm in Version {}'.format(version))
Noch schlimmer ist diese Version:
In [ ]:
version = '0.9 beta'
# Imports sollten immer ganz oben passieren, man kann sie aber überall verwenden
from sys import *
print('Sie verwenden MeinProgramm in Version {}'.format(version))
Hier haben wir alles aus dem Modul sys
in unseren eigenen Namespace importiert. Wir waren uns möglicherweise gar nicht bewusst, dass es in sys
eine Variable version
gibt, die unsere eigene Variable überlagert. Schwer zu findende Fehler sind so vorprogrammiert!
Kleiner Exkurs: wenn Sie feststellen wollen, was in einem Modul vorhanden (und was wir beim letzten Beispiel allen in unseren Namensraum importiert haben) ist, können Sie die dir()
Funktion verwenden:
In [ ]:
import sys
dir(sys)
Manche Namensräume sind sehr lange und es ist daher mühsam, diese immer einzutippen. Deshalb besteht die Möglichkeit, einem Modul einen eigenen Namen zuzuweisen. pyplot
ist ein Modul des mächtigen matplotlib
Pakets. (Achtung: Dieses Paket ist nicht in der Standard-Library und muss möglicherweise erst nachinstalliert werden).
Hier zuerst die umständliche Variante:
In [ ]:
import matplotlib.pyplot
matplotlib.pyplot.plot([1, 2, 3, 4, 4, 3, 5, 6, 6, 3, 3, 4])
matplotlib.pyplot.show()
Normalerweise schreibt man das allerdings so, um sich Tipparbeit zu sparen:
In [ ]:
import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4, 4, 3, 5, 6, 6, 3, 3, 4])
plt.show()
So wie eine Funktion durch einen Docstring beschrieben werden kann, funktioniert das auch für Module. Dazu muss man einfach direkt am Anfang der Modul-Datei den entsprechenden Docstring schreiben. Im Verzeichnis dieses Notebooks finden sie eine Datei (d.h. ein Modul) mystring.py. Da dieses Modul über einen DocString verfügt, können diesen auslesen:
In [ ]:
import mystring
help(mystring)
In [ ]:
mystring.reverse('abc')
In [ ]:
mystring.distinct_len('Mississippi')
Module können an unterschiedlichen Stellen im Filesystem liegen. Hier wird kurz beschrieben, wo und wie Python nach Modulen sucht. Dabei kommt eine bestimmte Reihenfolge zum Einsatz. Sobald das (oder zumindest ein gleichnamiges) Modul gefunden wird, wird dieses verwendet. Diese Reihenfolge ist:
PYTHONPATH
definiert sind.Das sys
-Modul weiß, wo gesucht wird:
In [ ]:
sys.path
sys.path
ist übrigens eine normale Liste, die z.B. erweitert werden kann (was aber, wenn Sie Ihr Programm weitergeben wollen, keine besonders gute Idee ist).
Wenn ein Modul zum ersten Mal von Python geladen wird, übersetzt es den Code in Bytecode und speichert diesen in eine eigene Datei, damit das Modul bei zukünftigen Aufrufen schneller geladen werden kann. Diese Bytecode-Dateien haben die Dateinamenerweiterung .pyc
und liegen unter Python3 im Verzeichnis __pycache__
. Sowohl dieses Verzeichnis als auch einzelne pyc
-Datei können gefahrlos gelöscht werden, weil Sie bei Bedarf automatisch neu erzeugt werden.
Wenn man größere Projekte tiefer organisieren will, kann man mehrere Module (und sogar Subpakete) zu einem Paket zusammenfassen.
Ein Paket ist nichts anderes, als ein Verzeichnis, das Module enthält. Zu einem
Paket wird ein solches Verzeichnis allerdings erst, wenn im Verzeichnis
eine Datei __init__.py
existiert. Diese Datei kann leer sein.
Ein Modul in einem Paket wird durch den Punkt-Operator getrennt angesprochen:
>>> import os
>>> if os.path.exists('daten.csv'):
...
Wenn man parallel an mehreren Projekten arbeitet oder fremde Python-Programme verwendet, kann es passieren, dass diese unterschiedle Bibliotheken benötigen, vielleicht sogar unterschiedliche Versionen derselben Bibliothek. Es ist daher sehr empfehlenswert, unterschiedliche, voneinander isolierte Python-Umgebungen zu verwenden. Diese sind allgemein für Python virtualenv
und für Conda bzw. Anaconda environments
.
Diese virtuellen Umgebungen isolieren Python weitgehend vom systemweit installierten Python. Ein Virtualenv verwendet zwar einen der systemweit installierten Python-Interpreter, alle zusätzlich installierten Pakete und Module sind jedoch spezifisch für diese eine Umgebung.
Dadurch ist es möglich, bestimmte Module nur für ein bestimmtes Projekt zu installieren oder ein Modul in unterschiedlichen Versionen für verschiedene Projekte zu verwenden.
Nicht zuletzt sind Virualenvs praktisch, um erste Experimente mit einem Zusatzmodul anzustellen ohne deshalb gleich das Modul systemweit installieren zu müssen.
Um die Verwaltung von virtuellen Python-Umgebungen kümmert sich ein
Programm mit dem Namen virtualenv
. Dieses muss zusätzlich zu
Python installiert werden. (IDEs wie PyCharm bringen virtualenv
automatisch mit).
Zunächst muss man ein Virtualenv anlegen:
virtualenv zielverzeichnis
bzw.
virtualenv -p c:\python3.5\bin\python zielverzeichnis
Die erste Zeile legt im Verzeichnis zielverzeichnis
eine neue virtuelle
Python-Umgebung an.
Falls man eine bestimmte Version von Python verwenden will, kann man diese
explizit mit der Option -p
angeben (letzte Zeile).
Danach (und zu Beginn jeder Arbeits-Sitzung) muss dieses Virtualenv aktiviert werden:
<venv-verzeichnis>\Scripts\activate # Windows
source <venv-verzeichnis>/bin/activate # OS X, Linux
Mit deactivate
kann man das Virualenv wieder deaktivieren.
Mit pip
lassen sich virtuelle Umgebungen relativ leicht dokumentieren:
pip freeze > requirements.txt
Die Datei requirements.txt
enthält nun Informationen über alle
installierten Zusatzmodule incl. Versionsinformation.
Um genau diese Zusatzmodule in einem neuen Virtualenv wieder zu installieren, reicht dieser Befehl:
pip install -r requirements.txt
Conda Environments funktioren von der Idee her sehr ähnlich wie virtuelle Environments.
Ein neues Environment wird so angelegt:
conda create --name myenv
Bei Bedarf kann auch hier eine bestimmte Python-Version angegeben werden:
conda create -n myenv python=3.2
Um ein Environment zu aktivieren muss unter Windows dieser Befehl eingegeben werden:
activate myenv
Unter OS X und Linux geht das Aktivieren so:
source activate myenv
Eine ausführliche Beschreibung zur Arbeit mit Environments findet sich hier: https://conda.io/docs/user-guide/tasks/manage-environments.html
In [ ]: