9. Die Importe
Der in Version 1 der Anwendungsübung aufgetretene Fehler veranlasst uns, die Rolle der Anweisung [import] näher zu betrachten.

9.1. Skripte [import_01]
Das Skript [imported] wird von verschiedenen Skripten (auch Module genannt) importiert:

# Modul importiert
# Diese Anweisung wird jedes Mal ausgeführt, wenn das Modul importiert wird
print("2")
# Variable, die zum importierten Modul gehört
x=4
Ein Modul wird ausgeführt, sobald es importiert wird. Wenn also das Modul [imported] importiert wird:
- wird die Zeile 3 angezeigt;
- wird die Variable x in Zeile 5 mit ihrem Wert belegt;
Das Skript [main_01] lautet wie folgt:
# Ein importiertes Modul wird ausgeführt
import imported
# Verwendung der Variablen x aus dem importierten Modul
print(imported.x)
- Zeile 2: Das Modul [imported] wird importiert. Dies führt zu seiner Ausführung:
- Der Wert 2 wird angezeigt;
- Die Variable x wird mit dem Wert 4 angelegt;
- Zeile 4: Die Variable x aus dem importierten Modul wird verwendet;
In PyCharm wird ein Fehler gemeldet:
In [1] weist PyCharm darauf hin, dass das Modul [imported] nicht bekannt ist. Technisch gesehen bedeutet dies, dass sich der Ordner, der das Modul [imported] enthält, nicht im Python-Pfad von PyCharm befindet. Der Python-Pfad ist die Gesamtheit der Verzeichnisse, in denen nach importierten Modulen gesucht wird. Um dieses Problem zu beheben, muss lediglich das Verzeichnis, in dem sich das Modul [imported] befindet – in diesem Fall das Verzeichnis [import/01] –, in [Sources root] deklariert werden:


Nach diesem Schritt wird der Ordner „[import/01]“ in den Python-Pfad von PyCharm aufgenommen und der Fehler verschwindet:

- Bei [1] hat der Ordner [01] seine Farbe geändert;
- bei [2-3] liegt kein Fehler mehr vor;
Die Ergebnisse der Ausführung lauten wie folgt:
Anmerkungen
- Zeile 2 ist das Ergebnis der Ausführung des importierten Moduls;
- Zeile 3 zeigt den Wert der Variablen x des importierten Moduls an;
Aus diesem Beispiel lässt sich das wichtige Konzept ableiten, dass ein importiertes Modul (oder Skript) ausgeführt wird.
Das Skript [main_02] lautet wie folgt:
# Die Variable x des importierten Moduls wird importiert
from imported import x
# sie wird angezeigt
print(x)
- In Zeile 2 sehen wir eine andere Syntax für den Import von [from module import objet1, objet2, …]. Hier wird die Variable [imported.x] importiert. Mit dieser Syntax wird die Variable x zu einer Variablen des Skripts [main_02]. Man muss ihr nicht mehr das Modul [imported] voranstellen;
- Zeile 4: Die Variable x aus [main_02] wird ausgegeben;
Die Ergebnisse der Ausführung lauten wie folgt:
Das Skript [main_03] lautet wie folgt:
# Es wird alles importiert, was im importierten Modul sichtbar ist
from imported import *
# Die Variable x aus dem importierten Modul wird verwendet
print(x)
Die Notation [import *] in Zeile 2 bedeutet, dass alle sichtbaren Objekte des importierten Moduls (Variablen, Funktionen) importiert werden.
Die Ergebnisse lauten wie folgt:
Das Skript [main_04] lautet wie folgt:
# Die Variable x aus dem importierten Modul wird importiert
# und benennen sie in y um
from imported import x as y
# Die Variable y wird ausgegeben
print(y)
Zeile 3 zeigt, dass man ein Objekt aus dem importierten Modul importieren und ihm einen Alias zuweisen kann. Hier wird die Variable [imported.x] zur Variable [main_04.y]. Die Ergebnisse sind dieselben wie zuvor.
9.2. Skript [import_02]

Das importierte Modul [module1.py] lautet hier wie folgt:
# eine Funktion
def f1():
print("f1")
Das importierte Modul definiert eine Funktion, was häufig vorkommt.
Das Skript [main_01] lautet wie folgt:
# import
import module1
# Ausführung von f1
module1.f1()
- Zeile 2: Das Modul wird importiert. Es wird ausgeführt. Hier wird nichts angezeigt;
- Zeile 4: Die Funktion [f1] des importierten Moduls wird ausgeführt;
Die Ergebnisse der Ausführung lauten wie folgt:
Hinweis: Um zu verhindern, dass PyCharm beim Import in Zeile 2 einen Fehler meldet, muss der Ordner, der [module1] enthält, in den Ordner von [Sources Root] von PyCharm verschoben werden:

In [1] wurde der Ordner [02], der in [Sources Root] abgelegt wurde, blau markiert. Es ist zu beachten, dass der gemeldete Fehler hier die korrekte Ausführung der Skripte nicht verhindert. Tatsächlich wird bei der Ausführung des Skripts [main_0x] der Ordner des Skripts automatisch in den Python-Pfad aufgenommen. Dadurch wird [module1] gefunden. Wenn nun auf einem Screenshot ein Ordner blau dargestellt wird, bedeutet dies, dass er in den [Sources Root] von PyCharm aufgenommen wurde.
Das Skript [main_02] lautet wie folgt:
# Import
from module1 import f1
# Ausführung von f1
f1()
- In Zeile 2 wird die Funktion [f1] aus dem Modul [module1] importiert;
- In Zeile 4 wird die Funktion f1 verwendet;
Die Ergebnisse sind identisch mit denen des Skripts [main_01].
9.3. Skripte [import_03]

Hinweis: [03] befindet sich im Projekt [Sources Root].
Die neuen Skripte importieren das Modul [module2], das sich nicht im selben Ordner wie sie befindet.
Das Skript [module2] lautet wie folgt:
# eine Funktion
def f2():
print("f2")
Das Skript definiert also eine Funktion [f2].
Das Skript [main_01] lautet wie folgt:
# Import des Moduls Class2
import dir1.module2
# Ausführung f2
dir1.module2.f2()
- Zeile 2: Es wird eine spezielle Notation verwendet, um anzugeben, wie das Modul [module2] zu finden ist. [dir1.module2] ist als Pfad [dir1/module2] zu lesen: Um [module2] zu finden, beginnt man im Ordner des aktuellen Skripts [main_01], wechselt dann zu [dir1] und findet dort [module2]. Dabei darf man nicht vergessen, dass der Ausgangspunkt des Pfades der Ordner des Skripts ist, das importiert wird;
- Zeile 4: Um die Funktion [f2] aus [module2] auszuführen;
Die Ergebnisse lauten wie folgt:
Zeile 2: das Ergebnis der Funktion [f2].
Das Skript [main_02] lautet wie folgt:
# Import des Moduls dir1.module2, das umbenannt wird
import dir1.module2 as module2
# Ausführung von f2
module2.f2()
Zeile 2: Das Modul [dir1.module] wird umbenannt, um die Schreibweise in Zeile 4 zu vereinfachen.
Das Skript [main_03] lautet wie folgt:
# Import der Funktion f2 aus dem Modul dir1.module2
from dir1.module2 import f2
# Ausführung von f2
f2()
Diesmal wird in Zeile 2 nur die Funktion [f2] importiert, die somit zu einer Funktion des Skripts [main_03] wird (Zeile 4).
Alle diese Skripte funktionieren sowohl im Kontext von PyCharm als auch in einer Python-Konsole. Der Grund dafür ist, dass in beiden Fällen der Ordner des ausgeführten Skripts – hier der Ordner „[03]“ – Teil des Python-Pfads ist. Dadurch wird der Ordner „[dir1/module2]“ gefunden.
9.4. Skripte [import_04]

Hier wurden die Ordner „[dir1]“ und „[dir2]“ in den Ordner „[Sources Root]“ des Projekts „PyCharm“ verschoben.
Das erste importierte Modul ist [module3]:
# eine Funktion
def f3():
print("f3")
Das zweite importierte Modul ist [module4]:
from module3 import f3
# eine Funktion
def f4():
f3()
print("f4")
- In Zeile 1 wird die Funktion [f3] aus [module3] importiert. Hier ist [module3] sichtbar, da man dessen Ordner [dir1] in den Ordner [Sources Root] verschoben hat;
- Zeilen 4–6: Es wird eine Funktion [f4] definiert, die die Funktion [f3] aus [module3] aufruft;
Das Hauptskript [main_01] lautet wie folgt:
# Modul4 wird importiert
from module4 import f4
# Ausführung f4
f4()
- In Zeile 2 wird das Modul [module4] importiert. Dieses ist sichtbar, da sein Ordner [dir2] in den Ordner [Sources Root] von PyCharm verschoben wurde;
- Zeile 4: Ausführung der Funktion [f4] aus [module4];
Die Ergebnisse der Ausführung von [main_01] in PyCharm lauten wie folgt:
Führen wir nun [main_01] in einem Python-Terminal (Konsole) aus:

Die Ergebnisse lauten wie folgt:
Was ist passiert? Das Python-Terminal hat keine Kenntnis vom Python-Path und von den Skripten [Sources Root] und PyCharm. Es verfügt über einen eigenen Python-Pfad. Darin befindet sich immer der Ordner des Skripts, das gerade ausgeführt wird, in diesem Fall das Skript [main_01]. Es kennt also den Ordner [import/04]. Im ausgeführten Skript findet es die Zeile:
from module4 import f4
Der Python-Interpreter sucht in den Verzeichnissen seines Python-Pfads nach [module4]. [module4] befindet sich jedoch nicht in [import/04] – das zwar im Python-Pfad enthalten ist –, sondern in [import/04/dir2], das dort nicht vorhanden ist. Daher der Fehler.
Wir haben es also mit einem bereits bekannten Problem zu tun: Ein Skript, das in PyCharm korrekt ausgeführt wird, kann im Kontext eines Python-Terminals abstürzen. Dies ist ein wiederkehrendes Problem, das wir lösen müssen.
9.5. Skripte [import_05]

Hinweis: Die Ordner [dir1] und [dir2] werden in den Python-Pfad aufgenommen. Es ist bereits zu beachten, dass hier ein Konflikt vorliegt: [module3] und [module4] werden an zwei Stellen im Python-Pfad von PyCharm gefunden:
- in [import/04/dir1] und [import/05/dir1] für [module3];
- in [import/04/dir2] und [import/05/dir2] für [module4];
Man kann dann [import/04/dir1] und [import/04/dir2] aus den [Sources Root] des Projekts PyCharm herausnehmen. Zufälligerweise ist [import/05/dir1] hier eine Kopie von [import/04/dir1] (das Gleiche gilt für [dir2]), sodass kein Problem vorliegt. Es sei jedoch angemerkt, dass man innerhalb von PyCharm auf die Ordnerliste von [Sources Root] achten muss, um Konflikte zu vermeiden.
Das Skript [main_01] sieht nun wie folgt aus:
import sys
# sys.path wird so geändert, dass es die Ordner enthält
# die die zu importierenden Klassen enthalten
sys.path.append(".")
sys.path.append("./dir1")
sys.path.append("./dir2")
# Modul4 wird importiert
from module4 import f4
# Ausführung F4
f4()
Wir versuchen, das Problem mit dem Python-Pfad zu lösen. Wir möchten einen Pfad, der sowohl unter PyCharm als auch in einem Python-Terminal funktioniert. Dazu werden wir das Problem selbst beheben.
- Zeilen 4–6: Wir fügen die Ordner [., ./dir1, ./dir2] zum Python-Pfad hinzu. Damit dies funktioniert, muss der aktuelle Ordner zum Zeitpunkt der Ausführung der Ordner [import/05] sein. Dies ist in PyCharm der Fall, aber nicht unbedingt in einem Python-Terminal, wie wir noch sehen werden;
- Zeile 8: Wir importieren [module4]. Nach den eben durchgeführten Schritten sollte es in [./dir2] gefunden werden;
Die Ausführung in PyCharm liefert folgende Ergebnisse:
Nun in einem Python-Terminal:
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\05>python main_01.py
f3
f4
Zeile 1: Der Ausführungsordner ist [import/05].
Gehen wir nun in der Verzeichnisstruktur von [import/05] eine Ebene zurück:
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\05>cd ..
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import>python 05/main_01.py
Traceback (most recent call last):
File "05/main_01.py", line 8, in <module>
from module4 import f4
ModuleNotFoundError: No module named 'module4'
- Zeile 2: Wenn [main_01] ausgeführt wird, befinden wir uns nicht mehr im Ordner [import/05], sondern in [import]. Wir haben jedoch geschrieben:
sys.path.append(".")
sys.path.append("./dir1")
sys.path.append("./dir2")
Dadurch werden die Ordner „[import, import/dir1, import/dir2]“ zum Python-Pfad hinzugefügt, was überhaupt nicht beabsichtigt ist. Beachten Sie, dass das Hinzufügen von nicht existierenden Ordnern (import/dir1, import/dir2) zum Python-Pfad keine Fehler verursacht.
Wir sind zwar einen Schritt weitergekommen, aber das reicht noch nicht aus. Dem Python-Pfad müssen keine relativen, sondern absolute Pfade hinzugefügt werden.
Das Skript [main_02] ist eine Variante von [main_01], die eine Konfigurationsdatei namens [config.json] verwendet:
{
"dependencies": [
"C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/import/05/dir1",
"C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/import/05/dir2"
]
}
Der Wert des Schlüssels [dependencies] ist die Liste der Ordner, die dem Python-Pfad hinzugefügt werden sollen. Beachten Sie, dass hier absolute und keine relativen Pfadnamen angegeben wurden.
Das Skript [main_02] verwendet die Datei [config.json] wie folgt:
import codecs
import json
import sys
# Konfigurationsdatei
config_filename="C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/import/05/config.json"
# Einlesen der JSON-Konfigurationsdatei
with codecs.open(config_filename, "r", "utf-8") as file:
config = json.load(file)
# Änderung von sys.path
for directory in config['dependencies']:
sys.path.append(directory)
# Modul4 wird importiert
from module4 import f4
# Ausführung von F4
f4()
- Zeile 6: Beachten Sie, dass der absolute Name der Konfigurationsdatei verwendet wurde;
- Zeilen 8–9: Die Konfigurationsdatei wird eingelesen. Aus ihrem Inhalt wird ein Wörterbuch [config] (Zeile 9) erstellt;
- Zeilen 11–13: Die Elemente des Arrays [config['dependencies']] werden dem Python-Pfad hinzugefügt. Da in [config.json] absolute Ordnernamen angegeben wurden, werden dem Python-Pfad absolute Namen hinzugefügt;
- Zeile 16: [module4] wird importiert. Es sollte gefunden werden, da sich [dir2] nun im Python-Pfad befindet;
Die Ausführung liefert dieselben Ergebnisse wie bei [main_02], außer dass das Skript weiterhin funktioniert, wenn der Ausführungsordner nicht mehr [import/05] ist:
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import>python 05/main_02.py
f3
f4
Zeile 1: Der Ausführungsverzeichnis ist [import].
Wir sind einen Schritt weitergekommen. Wir haben gesehen:
- dass wir den Python-Pfad selbst erstellen mussten;
- dass wir darin die absoluten Pfade aller Ordner angeben mussten, die die von der Anwendung importierten Module enthalten;
Allerdings ist die Verwendung absoluter Pfade in Skripten keine Lösung. Sobald das Projekt an einen anderen Standort verlagert wird, funktioniert es nicht mehr. Wir müssen eine andere Lösung finden.
9.6. Skripte [import_06]

Hinweis: Die Ordner „[06, dir1, dir2]“ wurden in die Ordner „[Sources Root]“ des Projekts „PyCharm“ verschoben. Die Ordner „[dir1, dir2]“ sind identisch mit denen aus den vorherigen Beispielen.
Die Datei [config.json] sieht wie folgt aus:
{
"rootDir": "C:/Data/st-2020/dev/python/cours-2020/v-02/imports/06",
"relativeDependencies": [
"dir1",
"dir2"
],
"absoluteDependencies": [
]
}
Wir führen zwei Arten von Pfaden ein:
- absolute Pfade, Zeilen 7–8;
- relative Pfade, Zeilen 3–6. Sie beziehen sich auf das Stammverzeichnis in Zeile 2. Wenn das Projekt also an einen anderen Speicherort verschoben wird, muss nur diese Zeile geändert werden;
Das Skript „[utils.py]“ nutzt die Datei „[config.json]“ und erstellt den Python-Pfad:
# Importe
import codecs
import json
import os
import sys
# Anwendungskonfiguration
def config_app(config_filename: str) -> dict:
# config_filename: Name der Konfigurationsdatei
# Ausnahmen werden weitergeleitet
# Auswertung der Konfigurationsdatei
with codecs.open(config_filename, "r", "utf-8") as file:
config = json.load(file)
# Hinzufügen der Abhängigkeiten zu sys.path
rootDir = config['rootDir']
# Die relativen Abhängigkeiten des Projekts werden zum Syspath hinzugefügt
for directory in config['relativeDependencies']:
# Die Abhängigkeit wird am Anfang des Syspaths hinzugefügt
sys.path.insert(0, f"{rootDir}/{directory}")
# Die absoluten Abhängigkeiten des Projekts werden dem Syspath hinzugefügt
for directory in config['absoluteDependencies']:
# Die Abhängigkeit wird am Anfang des Syspaths hinzugefügt
sys.path.insert(0, directory)
# Das Konfigurationswörterbuch wird erstellt
return config
# Ordner des ausgeführten Skripts
def get_scriptdir():
return os.path.dirname(os.path.abspath(__file__))
- Zeile 8: Die Funktion [config_app] erhält als Parameter den Namen der Konfigurationsdatei;
- Zeilen 12–14: Die Konfigurationsdatei wird verwendet, um das Wörterbuch [config] zu erstellen;
- Zeile 20: [sys.path] ist die Liste der Verzeichnisse im Python-Pfad;
- Zeilen 17–20: Die relativen Abhängigkeiten der Konfigurationsdatei werden dem Python-Pfad hinzugefügt. Sie werden am Anfang des Arrays [sys.path] (Zeile 20) eingefügt. Denn wenn Python nach einem Modul sucht, durchsucht es die Ordner des [sys.path] der Reihe nach. In diesem Dokument befinden sich jedoch Module mit denselben Namen in verschiedenen Verzeichnissen des [sys.path]. Indem die Abhängigkeiten der Anwendung an den Anfang des Arrays [sys.path] gesetzt werden, wird sichergestellt, dass diese vor anderen Ordnern des Arrays [sys.path] durchsucht werden, die Module mit denselben Namen enthalten könnten;
- Zeilen 21–24: Die absoluten Abhängigkeiten der Konfigurationsdatei werden dem Python-Pfad hinzugefügt;
- Zeile 26: Die Konfiguration der Anwendung wird zurückgegeben;
- Zeilen 29–30: Die Funktion [get_scriptdir] gibt den absoluten Namen des Ordners des aktuell ausgeführten Skripts zurück (in dem sich der Funktionsaufruf befindet);
Das Hauptskript [main] lautet wie folgt:
# Importe
import sys
from utils import config_app
def affiche_path(msg: str):
# Meldung
print(f"{msg}------------------------------")
# sys.path
for path in sys.path:
print(path)
# Hauptprogramm -------------
try:
# sys.path ist konfiguriert
affiche_path("avant....")
config = config_app(f"{get_scriptdir()}/config.json")
affiche_path("après....")
# Modul4 wird importiert
from module4 import f4
# Ausführung F4
f4()
except BaseException as erreur:
print(f"L'erreur suivante s'est produite : {erreur}")
finally:
print("done")
- Zeile 4: Die Funktion [config_app] wird importiert. Da sich [utils] und [main] im selben Ordner befinden, funktioniert [import] immer. Der Ordner des Hauptskripts wird nämlich automatisch zum Python-Path hinzugefügt;
- Zeilen 7–12: Die Funktion [affiche_path] zeigt die Liste der Ordner im Python-Pfad an;
- Zeile 19: Die Anwendung wird konfiguriert. Beachten Sie, dass der absolute Pfad der Konfigurationsdatei an die Funktion [config_app] übergeben wird. Nach dieser Anweisung wurde der Python-Pfad neu aufgebaut;
- Zeile 22: [module4] wird importiert. Dank des neu aufgebauten Python-Pfads wird dieses Modul gefunden;
- Zeile 24: Die Funktion [f4] wird ausgeführt;
Im Kontext von PyCharm sind die Ergebnisse der Ausführung wie folgt:
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/import/06/main.py
avant....------------------------------
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\06
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\fonctions\shared
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\impots\v01\shared
…
C:\Program Files\Python38\python38.zip
C:\Program Files\Python38\DLLs
C:\Program Files\Python38\lib
C:\Program Files\Python38
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\lib\site-packages
après....------------------------------
C:/Data/st-2020/dev/python/cours-2020/v-02/imports/06/dir2
C:/Data/st-2020/dev/python/cours-2020/v-02/imports/06/dir1
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\06
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\fonctions\shared
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\impots\v01\shared
….
C:\Program Files\Python38\python38.zip
C:\Program Files\Python38\DLLs
C:\Program Files\Python38\lib
C:\Program Files\Python38
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\lib\site-packages
f3
f4
done
Process finished with exit code 0
Anmerkungen
- Zeilen 2–13: Der Python-Pfad von PyCharm. Darin sind alle Ordner enthalten, die in den [Sources Root]-Dateien des Projekts abgelegt wurden;
- Zeilen 14–29: Der von der Funktion [config_app] erstellte Python-Pfad. In den Zeilen 15–16 finden sich die beiden von uns hinzugefügten Abhängigkeiten;
- Zeilen 22–27: die Systemordner des Python-Interpreters, der das Skript ausgeführt hat;
- Zeilen 28–29: Die Ausführung verläuft normal;
Begeben wir uns nun in den Kontext, der bisher einen Ausführungsfehler verursacht hat:
- Wir öffnen ein Python-Terminal;
- wechseln in ein anderes Verzeichnis als dasjenige, das das ausgeführte Skript enthält;
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import>python 06/main.py
avant....------------------------------
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\06
C:\Program Files\Python38\python38.zip
C:\Program Files\Python38\DLLs
C:\Program Files\Python38\lib
C:\Program Files\Python38
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\lib\site-packages
après....------------------------------
C:/Data/st-2020/dev/python/cours-2020/v-02/imports/06/dir2
C:/Data/st-2020/dev/python/cours-2020/v-02/imports/06/dir1
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\import\06
C:\Program Files\Python38\python38.zip
C:\Program Files\Python38\DLLs
C:\Program Files\Python38\lib
C:\Program Files\Python38
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\lib\site-packages
f3
f4
done
Diesmal klappt es (Zeilen 20–21). Man beachte, dass [sys.path] nicht dieselben Ordner enthält wie bei der Ausführung unter PyCharm.
9.7. Skripte [import_07]
Wir verbessern die vorherige Lösung in zweierlei Hinsicht:
- Wir ersetzen die Konfigurationsdatei [config.json] durch ein Skript [config.py]. Die Datei jSON weist nämlich ein großes Problem auf: Sie lässt sich nicht mit Kommentaren versehen. Das Wörterbuch „[config.json]“ kann durch ein Python-Wörterbuch ersetzt werden, das den Vorteil hat, dass es mit Kommentaren versehen werden kann;
- wir verwenden ein Modul, das für alle Python-Projekte auf dem Rechner sichtbar ist;
9.7.1. Installation eines maschinenweiten Moduls

Oben erstellen wir einen Ordner „[packages/myutils]“ im Projekt „PyCharm“ (die Namen spielen keine Rolle).
Das Skript [myutils.py] lautet wie folgt:
# Importe
import sys
import os
def set_syspath(absolute_dependencies: list):
# absolute_dependencies: eine Liste absoluter Ordnernamen
# Die absoluten Abhängigkeiten des Projekts werden zum Syspath hinzugefügt
for directory in absolute_dependencies:
# Es wird überprüft, ob der Ordner vorhanden ist
existe = os.path.exists(directory) and os.path.isdir(directory)
if not existe:
# Es wird eine Ausnahme ausgelöst
raise BaseException(f"[set_syspath] le dossier du Python Path [{directory}] n'existe pas")
else:
# Der Ordner wird an den Anfang des Syspaths hinzugefügt
sys.path.insert(0, directory)
- Zeilen 6–18: Die Funktion [set_syspath] erstellt einen Python-Pfad mit der Liste der Ordner, die ihr als Parameter übergeben werden;
- Zeilen 12–15: Es wird überprüft, ob der Ordner, der in den Python-Pfad aufgenommen werden soll, existiert;
Das Skript [__init.py__] (zwei Unterstriche vor und hinter dem Namen; dieser ist vorgeschrieben) lautet wie folgt:
from .myutils import set_syspath
Wir importieren die Funktion [set_syspath] aus dem Skript [myutils]. Die Notation [.myutils] bezeichnet den Pfad [./myutils], also das Skript [myutils], das sich im selben Ordner wie [__init.py] befindet. Man hätte auch die Notation [myutils] verwenden können. Allerdings werden wir ein Modul [myutils] mit maschinenweitem Geltungsbereich erstellen. Daher würde die Notation [from myutils import set_syspath] dann mehrdeutig werden. Ist damit das Skript [myutils] aus dem aktuellen Ordner gemeint oder das maschinenweite Skript [myutils]? Die Notation [.myutils] beseitigt diese Mehrdeutigkeit.
Das Skript [setup.py] (auch hier ist der Name vorgegeben) lautet wie folgt:
from setuptools import setup
setup(name='myutils',
version='0.1',
description='Utilitaire fixant le Python Path',
url='#',
author='st',
author_email='st@gmail.com',
license='MIT',
packages=['myutils'],
zip_safe=False)
In diesem Skript wird das Modul beschrieben, das erstellt werden soll. Hier erstellen wir es lokal. Der gleiche Prozess wird jedoch auch zur Erstellung eines offiziell vertriebenen Moduls verwendet (siehe |pypi|). Die wichtigsten Punkte sind dabei folgende:
- Zeile 3: der Name des erstellten Moduls;
- Zeile 4: die Version des Moduls;
- Zeile 5: die Beschreibung des Moduls;
- Zeilen 7–8: der Autor des Moduls;
Um dieses Modul mit einem maschinenweiten Geltungsbereich zu installieren, gehen wir wie folgt vor:

Anschließend gibt man im Python-Terminal den folgenden Befehl ein: [pip install .]:
(venv) C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\packages>pip install .
Processing c:\data\st-2020\dev\python\cours-2020\python3-flask-2020\packages
Using legacy setup.py install for myutils, since package 'wheel' is not installed.
Installing collected packages: myutils
Attempting uninstall: myutils
Found existing installation: myutils 0.1
Uninstalling myutils-0.1:
Successfully uninstalled myutils-0.1
Running setup.py install for myutils ... done
Successfully installed myutils-0.1
Ab sofort kann jedes Skript der Maschine das Modul [myutils] importieren, ohne dass dieses im Projektcode enthalten ist.
9.7.2. Das Skript [config.py]

Das Skript [config.py] sorgt für die Konfiguration der Anwendung:
def configure():
import os
# absoluter Pfad des Konfigurationsskripts
script_dir = os.path.dirname(os.path.abspath(__file__))
# Absolute Pfade der Ordner, die in den Syspath aufgenommen werden sollen
absolute_dependencies = [
# lokale Ordner
f"{script_dir}/dir1",
f"{script_dir}/dir2",
]
# Aktualisierung des Syspath
from myutils import set_syspath
set_syspath(absolute_dependencies)
# Die Konfiguration wird zurückgegeben
return {}
- Zeile 1: Die Funktion [configure] sorgt für die Konfiguration der Anwendung;
- Zeilen 7–10: das Wörterbuch, das zuvor in [config.json] enthalten war;
- Zeilen 9–10: Da es sich um ein Skript handelt, können die absoluten Namen der Ordner „[dir1, dir2]“ direkt verwendet werden;
- Zeilen 12–14: Wir verwenden die Funktion [set_syspath] aus dem soeben erstellten Modul [myutils], um den Python-Pfad der Konfiguration festzulegen;
- Zeile 20: Wir geben das Wörterbuch der Anwendungskonfiguration zurück. Hier ist es leer;
9.7.3. Das Skript [main.py]
Das Hauptskript [main] lautet wie folgt:
# Die Anwendung wird konfiguriert
import config
config = config.configure()
# Der Syspath ist konfiguriert – die Importe können durchgeführt werden
from module4 import f4
# Hauptprogramm -------------
try:
f4()
except BaseException as erreur:
print(f"L'erreur suivante s'est produite : {erreur}")
finally:
print("done")
- Zeilen 2–4: Die Anwendung wird mithilfe des Moduls [config.py] konfiguriert. Dieses ist verfügbar, da es sich im selben Ordner wie das Hauptskript befindet. Der Ordner des Hauptskripts ist jedoch immer Teil des Python-Pfads;
- Wenn man zu Zeile 6 gelangt, wurde der Python-Pfad bereits so aufgebaut, dass er den Ordner des Moduls [module4] enthält. Dieses Modul kann daher in Zeile 7 importiert werden;
- Zeilen 10–15: Nun muss nur noch die Funktion [f4] ausgeführt werden;
Die Ergebnisse der Ausführung in PyCharm lauten wie folgt:
In einem Python-Terminal und außerhalb des Ordners des Hauptskripts lauten die Ergebnisse wie folgt:
Von nun an werden wir bei der Konfiguration einer Anwendung immer wie folgt vorgehen:
- Vorhandensein eines Skripts [config.py] im Ordner des Hauptskripts. Dieses Skript enthält eine Funktion [configure], die zwei Zwecke erfüllt:
- den Python-Pfad für die Anwendung erstellen. Dazu listet [config.py] alle Ordner auf, die die von der Anwendung verwendeten Module enthalten, und erstellt den Python-Pfad mit deren absoluten Namen;
- das [config]-Wörterbuch mit der Anwendungskonfiguration erstellen;
Wir wenden dieses Schema auf die zweite Version der Anwendungsübung an. Wir erinnern uns nämlich daran, dass Version 1 in der Umgebung PyCharm funktionierte, nicht jedoch in einem Python-Terminal. Das Problem lag am Python-Pfad.