Module importieren
Im Artikel über Scripte in Python sind wir bereits darüber gestolpert: das import Statement. Wir haben in diesem Script ein weiteres Script bzw „Modul“ importiert, und waren somit in der Lage auf Variablen und Funktionen dieses importierten Moduls zuzugreifen. Doch was passiert eigentlich genau wenn der Python Interpreter ein import Statement verarbeitet, und welche Varianten gibt es neben dem bereits verwendetem „import x“ weiterhin?
Eine Standard-Installation von Python bietet bereits eine Fülle von Modulen und Paketen mit denen ein Programmierer direkt starten kann. Ich werde hier ein paar dieser Standard-Module benutzen, um das import Statement näher zu erläutern. Eine Liste aller verfügbaren Module findet sich im Python Module Index.
Das es sich bei „import“ um ein Statement handelt, gibt es hier keine Klammern oder Anführungszeichen bei dem sich anschließenden Modulnamen. Genauso wenig gibt es hier Rückgabewerte. Der Modulname legt zudem zwei Dinge fest: zum einen das Modul, das gesucht und import werden soll, zum anderen den Variablennamen, unter dem das Modul nachfolgend angesprochen werden kann.
Im folgenden Code Stück wird das Modul „os“ (Miscellaneous operating system interfaces) importiert. „os“ ist nun der Name der Variable, die wir für den Zugriff auf Funktionen oder Attribute des importieren Moduls benutzen können. Wir rufen die Funktion „getcwd“ auf.
import os
os.getcwd()
Direkter Import
Durch den Import des gesamten Moduls können wir auf alle darin „global“ definierten Funktionen und Variablen über „os.“ zugreifen.
Hier finden wir alle Funktionen und Variablen des python internen os Moduls https://docs.python.org/3/library/os.html
Angenommen wir benötigen ausschließlich die Funktion „getcwd“ und die restlichen Funktionen und Variablen des os Moduls werden wir in unserem Projekt nicht benutzen. Hierfür bietet Python die Möglichkeit Funktionen oder Variablen eines Moduls direkt zu importieren:
from „module“ import „function_or_variable“
Wir sagen also mit dem folgenden Import Statement, dass ausschließlich die Funktion „getcwd“ aus dem Modul „os“ importiert und als Variable „getcwd“ verfügbar sein soll.
from os import getcwd
getcwd()
Konkreter Import
Sollte es bei komplexeren Projekten einmal dazu kommen, dass wir Funktionen oder Variablen aus verschiedenen Modulen importieren, die gleich benannt sind, so können wir beim Import Statement direkt bestimmen, welchen Variablennamen diese im aktellen Kontext erhalten sollen.
Beispiel: Wir haben ein komplexes Projekt mit einer ebay und einer amazon Schnittstelle, beide haben eine Methode „get_products“, die je nachdem Produkte des einen oder anderen Dienstes abruft. Beide Methoden möchten wir gern im unser Modul importieren, später aber klar unterscheiden und benutzen können. Wir erledigen die Importe wie folgt:
from „module“ import „function_or_variable“ as „new_funtion_or_variable_name“
from amazon import get_products as get_amazon_products
from ebay import get_products as get_ebay_products
my_amazon_products = get_amazon_products()
my_ebay_products = get_ebay_products()
Auch wenn dieses Vorgehen funktioniert, so rate ich davon ab, diese Art und Weise des Imports zu nutzen. Funktions- und Variablennamen können damit maskiert bzw verschleiert werden und z.B. durch die Programmierumgebung nicht mehr korrekt aufgelöst werden. Eine mögliche Lösung für unser konkretes Beispiel wäre die Nutzung einer Factory, die den jeweiligen import kapselt und die gewünschte Methode zurückgibt.
Funktionsweise
Wie findet nun Python durch das import Statement die jeweiligen Module bzw Pakete?
Python durchsucht dafür der Reihe nach die Such-Pfade, welche durch die Variable sys.path definiert werden (die Reihenfolge spielt hier eine wichtige Rolle)
Der erste durchsuchte Pfad “ ist dabei immer das aktuelle Arbeitsverzeichnis, erst anschließend kommen ‚lib‘ Verzeichnisse und evtl. selbst definierte und hinzugefügte Verzeichnisse.
Sobald Python ein Modul oder Paket mit dem gesuchten Namen findet, wird dieses importiert, d.h. es wird zeilenweise durchlaufen und der Inhalt wie oben beschrieben in der jeweiligen Variable gespeichert.
>>> import sys
>>> for p in sys.path:
... print(p)
...
/usr/lib/python35.zip
/usr/lib/python3.5
/usr/lib/python3.5/plat-x86_64-linux-gnu
/usr/lib/python3.5/lib-dynload
/usr/local/lib/python3.5/dist-packages
/usr/lib/python3/dist-packages
Findet Python kein Modul oder Paket mit dem gegebenen Namen, wird ein ImportError geworfen.
>>> import unknown_package
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named 'unknown_package'