Wie kann ich ein Modul dynamisch importieren, wenn der vollständige Pfad angegeben ist?

Lesezeit: 7 Minuten

Benutzeravatar von derfred
derfred

Wie lade ich ein Python-Modul mit seinem vollständigen Pfad?

Beachten Sie, dass sich die Datei überall im Dateisystem befinden kann, wo der Benutzer Zugriffsrechte hat.


Siehe auch: Wie importiert man ein Modul mit seinem Namen als String?

  • Schöne und einfache Frage – und nützliche Antworten, aber sie lassen mich fragen, was mit dem Python-Mantra “There is eines offensichtlich Weg”, es zu tun.. Es scheint nicht wie eine einzelne oder einfache und offensichtliche Antwort darauf zu sein.. Scheint lächerlich hacky und versionsabhängig für eine so grundlegende Operation (und es sieht in neueren Versionen aufgebläht aus. .).

    – Finger

    6. Dezember 2019 um 12:08 Uhr

  • @inger was mit dem Python-Mantra “Es gibt einen offensichtlichen Weg” passiert ist, es zu tun […] [not] eine einzelne oder eine einfache und offensichtliche Antwort darauf […] lächerlich hackig[…] mehr aufgebläht in neueren Versionen Willkommen in der schrecklichen Welt der Python-Paketverwaltung. Pythons import, virtualenv, pip, setuptools whatnot sollte alles weggeworfen und durch funktionierenden Code ersetzt werden. Ich habe gerade versucht zu groken virtualenv oder war es pipenv und musste das Äquivalent eines Jumbo-Jet-Handbuchs durcharbeiten. Wie diese Erfindung als Die Lösung für den Umgang mit Tiefen vorgeführt wird, ist mir völlig entgangen.

    – John Frazer

    26. Juni 2020 um 20:59 Uhr


  • relevante XKCD xkcd.com/1987

    – John Frazer

    26. Juni 2020 um 21:08 Uhr

  • @JohnFrazer es wurde noch schlimmer durch das ständige Nörgeln von Leuten, die sich nicht die Mühe machen konnten, 2 Absätze der Dokumentation zu lesen. Ihr XKCD ist nicht wirklich relevant, da es zeigt, was diese Art von Leuten erreichen können, wenn sie Dinge ausprobieren, bis etwas funktioniert. Nur weil es einen neuen Weg gibt, heißt das nicht, dass es jetzt “zwei offensichtliche Wege” gibt. Der alte Weg ist für einige Fälle offensichtlich, der neue Weg bringt Benutzerfreundlichkeit in andere. Das passiert, wenn Sie sich wirklich für DevX interessieren.

    – Błażej Michalik

    2. Dezember 2020 um 0:13 Uhr


  • Und denken Sie, dass Java oder sogar PHP (heutzutage) eine klare und einfache Möglichkeit haben, Dinge in Pakete/Namespaces aufzuteilen und wiederzuverwenden. Es ist ein Schock, einen solchen Schmerz in Python zu sehen, der die Einfachheit in jedem anderen Aspekt angenommen hat.

    – Alex

    27. Januar 2021 um 7:46 Uhr

Der Vorteil des Hinzufügens eines Pfads zu sys.path (gegenüber der Verwendung von imp) besteht darin, dass es die Dinge vereinfacht, wenn mehr als ein Modul aus einem einzelnen Paket importiert wird. Zum Beispiel:

import sys
# the mock-0.3.1 dir contains testcase.py, testutils.py & mock.py
sys.path.append('/foo/bar/mock-0.3.1')

from testcase import TestCase
from testutils import RunTests
from mock import Mock, sentinel, patch

  • Wie verwenden wir sys.path.append auf eine einzelne Python-Datei statt auf ein Verzeichnis verweisen?

    – Phani

    13. Januar 2014 um 17:46 Uhr

  • 🙂 Vielleicht wäre Ihre Frage besser als StackOverflow-Frage geeignet, nicht als Kommentar zu einer Antwort.

    – Daryl Spitzer

    6. März 2015 um 0:12 Uhr

  • Der Python-Pfad kann Zip-Archive, “Eier” (eine komplexe Art von Zip-Archiven) usw. enthalten. Module können daraus importiert werden. Die Pfadelemente sind es also tatsächlich Behälter von Dateien, aber sie sind nicht notwendigerweise Verzeichnisse.

    – alexis

    30. April 2015 um 21:21 Uhr

  • Beachten Sie, dass Python import-Anweisungen zwischenspeichert. In dem seltenen Fall, dass Sie zwei verschiedene Ordner haben, die einen einzigen Klassennamen (classX) teilen, funktioniert der Ansatz, einen Pfad zu sys.path hinzuzufügen, classX zu importieren, den Pfad zu entfernen und für die verbleibenden Pfade zu wiederholen, nicht. Python lädt die Klasse immer vom ersten Pfad aus seinem Cache. In meinem Fall wollte ich ein Plugin-System erstellen, bei dem alle Plugins eine bestimmte KlasseX implementieren. Am Ende habe ich SourceFileLoader verwendet, beachten Sie, dass dies der Fall ist Abwertung ist umstritten.

    – ComFreek

    3. Juli 2015 um 17:18 Uhr


  • Beachten Sie, dass dieser Ansatz es dem importierten Modul ermöglicht, andere Module aus demselben Verzeichnis zu importieren, was Module häufig tun, während der Ansatz der akzeptierten Antwort dies nicht tut (zumindest in 3.7). importlib.import_module(mod_name) kann hier anstelle des expliziten Imports verwendet werden, wenn der Modulname zur Laufzeit nicht bekannt ist, würde ich a hinzufügen sys.path.pop() Am Ende wird jedoch angenommen, dass der importierte Code nicht versucht, weitere Module zu importieren, wenn er verwendet wird.

    – Eli_B

    6. Mai 2019 um 21:45 Uhr

  • Diese “Temp”-Lösung ist eine großartige Antwort, wenn Sie ein Projekt in einem Jupyter-Notebook an anderer Stelle herumprobieren möchten.

    – fordy

    16. November 2018 um 17:20 Uhr

  • Aber … es ist gefährlich, den Pfad zu manipulieren

    – Shai Alon

    10. November 2019 um 15:56 Uhr

  • @ShaiAlon Sie fügen Pfade hinzu, also keine andere Gefahr, als wenn Sie Codes von einem Computer auf einen anderen übertragen, könnten Pfade durcheinander gebracht werden. Für die Paketentwicklung importiere ich also nur lokale Pakete. Außerdem sollten Paketnamen eindeutig sein. Wenn Sie sich Sorgen machen, verwenden Sie die vorübergehende Lösung.

    – Miladious

    13. November 2019 um 0:11 Uhr


  • Ich hatte Schwierigkeiten, meine Unit-Tests zu importieren, und Ihre Temp funktionierte gut. Ich habe es so geändert, dass es aus demselben Verzeichnis wie Unit Test importiert wird mit: >>> import os >>> import sys >>> sys.path.append(os.getcwd())

    – Braumanz

    19. September um 3:45


Benutzeravatar von Sam Gröndahl
Sam Gröndahl

Wenn Ihr Top-Level-Modul keine Datei ist, sondern als Verzeichnis mit __init__.py gepackt ist, dann funktioniert die akzeptierte Lösung fast, aber nicht ganz. In Python 3.5+ wird der folgende Code benötigt (beachten Sie die hinzugefügte Zeile, die mit ‘sys.modules’ beginnt):

MODULE_PATH = "/path/to/your/module/__init__.py"
MODULE_NAME = "mymodule"
import importlib
import sys
spec = importlib.util.spec_from_file_location(MODULE_NAME, MODULE_PATH)
module = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = module 
spec.loader.exec_module(module)

Wenn exec_module ohne diese Zeile ausgeführt wird, versucht es, relative Importe in Ihrer __init__.py der obersten Ebene an den Modulnamen der obersten Ebene zu binden – in diesem Fall „mymodule“. Aber “mymodule” ist noch nicht geladen, daher erhalten Sie den Fehler “SystemError: Parent module ‘mymodule’ not installed, cannot perform relative import”. Sie müssen also den Namen binden, bevor Sie ihn laden. Der Grund dafür ist die fundamentale Invariante des relativen Importsystems: „The invariant holding is that if you have sys.modules[‘spam’] und sys.modules[‘spam.foo’] (wie Sie es nach dem obigen Import tun würden), muss letzteres als foo-Attribut des ersteren erscheinen. wie hier besprochen.

  • Danke vielmals! Diese Methode ermöglicht relative Importe zwischen Submodulen. Groß!

    – tebanep

    10. Oktober 2019 um 14:09 Uhr

  • Diese Antwort stimmt mit der Dokumentation hier überein: docs.python.org/3/library/….

    – Tim Ludwinski

    9. Dezember 2019 um 16:08 Uhr

  • aber was ist mymodule?

    – Gülzar

    20. Januar 2020 um 10:02 Uhr

  • @Gulzar, es ist ein beliebiger Name, den Sie Ihrem Modul geben möchten, damit Sie später Folgendes tun können: “from mymodule import myclass”

    – Ido

    16. Februar 2020 um 22:44 Uhr

  • Obwohl unkonventionell, wenn Ihr Paketeintrittspunkt etwas anderes als ist __init__.py, können Sie es trotzdem als Paket importieren. Enthalten spec.submodule_search_locations = [os.path.dirname(MODULE_PATH)] nach dem Erstellen der Spezifikation. Sie können auch a behandeln __init__.py als Nicht-Paket (z. B. einzelnes Modul), indem Sie diesen Wert auf setzen None

    – Asmisow

    5. November 2020 um 20:32 Uhr

Benutzeravatar von Peter Mortensen
Peter Mortensen

Es hört sich so an, als ob Sie die Konfigurationsdatei nicht speziell importieren möchten (was eine ganze Menge Nebenwirkungen und zusätzliche Komplikationen mit sich bringt). Sie möchten es einfach ausführen und auf den resultierenden Namespace zugreifen können. Die Standardbibliothek stellt dafür eine spezielle API in Form von bereit runpy.run_path:

from runpy import run_path
settings = run_path("/path/to/file.py")

Diese Schnittstelle ist in Python 2.7 und Python 3.2+ verfügbar.

  • Danke vielmals! Diese Methode ermöglicht relative Importe zwischen Submodulen. Groß!

    – tebanep

    10. Oktober 2019 um 14:09 Uhr

  • Diese Antwort stimmt mit der Dokumentation hier überein: docs.python.org/3/library/….

    – Tim Ludwinski

    9. Dezember 2019 um 16:08 Uhr

  • aber was ist mymodule?

    – Gülzar

    20. Januar 2020 um 10:02 Uhr

  • @Gulzar, es ist ein beliebiger Name, den Sie Ihrem Modul geben möchten, damit Sie später Folgendes tun können: “from mymodule import myclass”

    – Ido

    16. Februar 2020 um 22:44 Uhr

  • Obwohl unkonventionell, wenn Ihr Paketeintrittspunkt etwas anderes als ist __init__.py, können Sie es trotzdem als Paket importieren. Enthalten spec.submodule_search_locations = [os.path.dirname(MODULE_PATH)] nach dem Erstellen der Spezifikation. Sie können auch a behandeln __init__.py als Nicht-Paket (z. B. einzelnes Modul), indem Sie diesen Wert auf setzen None

    – Asmisow

    5. November 2020 um 20:32 Uhr

Benutzeravatar von Peter Mortensen
Peter Mortensen

Sie können auch so etwas tun und das Verzeichnis, in dem sich die Konfigurationsdatei befindet, zum Python-Ladepfad hinzufügen und dann einfach einen normalen Import durchführen, vorausgesetzt, Sie kennen den Namen der Datei im Voraus, in diesem Fall “config”.

Fummelig, aber es funktioniert.

configfile="~/config.py"

import os
import sys

sys.path.append(os.path.dirname(os.path.expanduser(configfile)))

import config

  • Das ist nicht dynamisch.

    – Shai Alon

    10. November 2019 um 16:10 Uhr

  • Ich habe versucht: config_file = ‘setup-for-chats’, setup_file = get_setup_file(config_file + “.py”), sys.path.append(os.path.dirname(os.path.expanduser(setup_file))), import config_file >> “ImportError: No module named config_file”

    – Shai Alon

    10. November 2019 um 16:17 Uhr


1436620cookie-checkWie kann ich ein Modul dynamisch importieren, wenn der vollständige Pfad angegeben ist?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy