HOWTO · Python
Importieren eines Moduls aus einem vollständigen Dateipfad in Python
In diesem Artikel erfahren Sie, wie Sie eine Python-Datei aus einem Pfad importieren.
Auf dieser Seite
Ein Modul über einen bestimmten Dateipfad zu laden ist nützlich, wenn sich ein Plugin, eine erzeugte Datei oder ein eigenständiges Skript außerhalb der üblichen Paketstruktur befindet. Für einen einmaligen Modulimport erstellt importlib.util ein Modulobjekt; sein Loader führt die Datei im Namensraum dieses Moduls aus. Registrieren Sie das Modul vor der Ausführung in sys.modules, damit Code, der während der Initialisierung die Modulregistrierung abfragt, das eigene Modul findet.
Eine Python-Datei mit importlib.util über ihren Pfad importieren
Geben Sie der Datei einen gültigen Python-Modulnamen und einen exakten Pfad. Der Name ist ein Bezeichner für das Modulobjekt. Er muss nicht mit dem Dateinamen übereinstimmen, sollte für Ihre Anwendung aber eindeutig genug sein. Das Beispiel erstellt eine temporäre Python-Datei und kann daher unabhängig vom aktuellen Arbeitsverzeichnis ausgeführt werden.
Führen Sie dieses Beispiel aus:
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
from pathlib import Path
import importlib.util
import sys
import tempfile
with tempfile.TemporaryDirectory() as directory:
module_path = Path(directory) / "greeting.py"
module_path.write_text("def message():\n return 'loaded from path'\n", encoding="utf-8")
module_name = "greeting_from_path"
spec = importlib.util.spec_from_file_location(module_name, module_path)
module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = module
spec.loader.exec_module(module)
print(module.message())
Der letzte Aufruf gibt den Wert aus, den die Funktion in der geladenen Datei zurückgibt. spec_from_file_location() erstellt eine Modulspezifikation, die Name und Speicherort beschreibt. module_from_spec() erstellt daraus das Modul, und exec_module() führt dessen Quelltext über den Loader aus. Wenn der Pfad dynamisch übergeben wird, prüfen Sie vor diesem Vorgehen, ob Spezifikation und Loader verfügbar sind. Eine fehlende Datei oder ein nicht unterstützter Loader lässt sich auf diesem Weg nicht importieren.
Das Verzeichnis der Datei zu sys.path hinzufügen
Wenn Sie gewöhnliche Imports aus einem Verzeichnis verwenden möchten, fügen Sie das Verzeichnis, in dem die Datei liegt, zu sys.path hinzu und importieren Sie das Modul anschließend über seinen Namen. sys.path enthält die Verzeichnisse, die Python bei der Suche nach Imports durchsucht. Dieses eigenständige Beispiel erstellt ein Modul in einem temporären Verzeichnis, fügt dessen Verzeichnis hinzu und importiert das Modul über seinen Namen:
Führen Sie dieses Beispiel aus:
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
from pathlib import Path
import importlib
import sys
import tempfile
with tempfile.TemporaryDirectory() as directory:
module_name = f"greeting_{Path(directory).name}"
module_path = Path(directory) / f"{module_name}.py"
module_path.write_text("def message():\n return 'loaded by name'\n", encoding="utf-8")
sys.path.insert(0, directory)
try:
module = importlib.import_module(module_name)
print(module.message())
finally:
sys.path.remove(directory)
sys.modules.pop(module_name, None)
Das Anhängen oder Einfügen eines Verzeichnisses verändert das Suchverhalten für den Rest des laufenden Prozesses. Beschränken Sie eine solche Pfadänderung daher möglichst auf den nötigen Umfang und fügen Sie keine Verzeichnisse hinzu, die von nicht vertrauenswürdigen Benutzern kontrolliert werden. Das Beispiel entfernt anschließend seinen Pfadeintrag und das zwischengespeicherte Modul, um die Auswirkungen zu begrenzen. Diese Methode ist praktisch, wenn Sie bewusst die normale Importsyntax verwenden oder mehrere Module aus demselben Verzeichnis laden möchten. Es gelten weiterhin die üblichen Regeln für Namensauflösung und Zwischenspeicherung: Ein bereits in sys.modules vorhandenes Modul kann wiederverwendet werden, und ein kollidierender Name kann unerwartet auf eine andere Datei verweisen.
exec() nur zum Ausführen vertrauenswürdigen Skripttexts verwenden
exec() führt Python-Quelltext in einem bereitgestellten Namensraum aus; dabei wird kein gewöhnliches Modulobjekt erstellt und registriert. Verwenden Sie es nur, wenn Sie vertrauenswürdigen Skriptinhalt ausführen möchten, nicht als Ersatz für den Import eines Moduls. Quelltext aus einem Upload, einer Anfrage oder einer anderen nicht vertrauenswürdigen Quelle kann beliebigen Python-Code mit den Berechtigungen des Prozesses ausführen. Ein separates Dictionary kann die vom Skript angelegten Namen aufnehmen, bietet aber weder das vollständige Importverhalten noch die Modulidentität eines echten Moduls.
Modulnamen, Pakete und Importfehler behandeln
Verwenden Sie für einen einfachen Modulnamen einen gültigen Bezeichner und wählen Sie einen stabilen, eindeutigen Namen, wenn Sie mehrere Dateien laden. Ein wiederverwendeter Name wirkt sich auf sys.modules aus: Wenn Sie unter diesem Namen eine andere Datei laden, kann der Eintrag in der Modulregistrierung ersetzt werden; ein späterer gewöhnlicher Import kann dagegen ein bereits zwischengespeichertes Modul zurückgeben. Legen Sie fest, ob wiederholte Aufrufe dasselbe Modul wiederverwenden oder bewusst ein neues laden sollen.
Eine direkt über ihren Pfad geladene Datei gehört nicht automatisch zu ihrem Paket. Code mit relativen Imports wie from .helpers import value benötigt einen Paketkontext, den eine Spezifikation für eine einzelne Datei nicht von selbst herstellt. Bei einem Paket empfiehlt es sich, über den Paketnamen zu importieren und dafür das übergeordnete Verzeichnis in sys.path verfügbar zu machen. Schlägt das Laden fehl, prüfen Sie, ob der Pfad auf eine lesbare Python-Datei verweist, ob die Spezifikation erstellt wurde und ob ein Loader vorhanden ist. Lesen Sie anschließend den Traceback der Modulausführung, um die Ursache zu ermitteln. Auch Code, der beim Import ausgeführt wird, kann fehlschlagen; ein gültiger Pfad allein garantiert daher keine erfolgreiche Initialisierung.
Den passenden Ansatz auswählen
Verwenden Sie importlib.util für einen einmaligen Import über einen bestimmten Dateipfad, wenn Sie ein Modulobjekt benötigen. Fügen Sie ein Verzeichnis zu sys.path hinzu, wenn es bei der gewöhnlichen Importsuche berücksichtigt werden soll, insbesondere wenn Sie mehrere zusammengehörige Module benötigen. Verwenden Sie exec() nur, wenn Sie vertrauenswürdigen Quelltext als Skript ausführen möchten und keine Modulsemantik benötigen. Für wiederverwendbaren Projektcode erleichtern ein reguläres Paket und gewöhnliche Imports meist den Umgang mit Abhängigkeiten, Namen und Zwischenspeicherung.