Wie kann ich ein Python-Modul mit seinem vollständigen Pfad laden? Beachten Sie, dass sich die Datei an einer beliebigen Stelle im Dateisystem befinden kann, da es sich um eine Konfigurationsoption handelt.
1139
Wie kann ich ein Python-Modul mit seinem vollständigen Pfad laden? Beachten Sie, dass sich die Datei an einer beliebigen Stelle im Dateisystem befinden kann, da es sich um eine Konfigurationsoption handelt.
Antworten:
Für Python 3.5+ verwenden Sie:
Verwenden Sie für Python 3.3 und 3.4:
(Obwohl dies in Python 3.4 veraltet ist.)
Für Python 2 verwenden Sie:
Es gibt äquivalente Komfortfunktionen für kompilierte Python-Dateien und DLLs.
Siehe auch http://bugs.python.org/issue21436 .
quelle
__import__
.imp.load_source
setzt nur den Wert des.__name__
zurückgegebenen Moduls. Das Laden wird nicht beeinflusst.imp.load_source()
bestimmt den Schlüssel des neuen Eintrags, der imsys.modules
Wörterbuch erstellt wurde, sodass das erste Argument tatsächlich das Laden beeinflusst.imp
Modul ist seit Version 3.4 veraltet: Für dasimp
Paket steht die Verwerfung zugunsten von ausimportlib
.Das Hinzufügen eines Pfads zu sys.path (gegenüber der Verwendung von imp) hat den Vorteil, dass beim Importieren von mehr als einem Modul aus einem einzelnen Paket die Arbeit vereinfacht wird. Zum Beispiel:
quelle
sys.path.append
verweisen wir auf eine einzelne Python-Datei anstelle eines Verzeichnisses?importlib.import_module(mod_name)
kann hier anstelle des expliziten Imports verwendet werden, wenn der Modulname zur Laufzeit nicht bekannt ist. Amsys.path.pop()
Ende würde ich jedoch ein hinzufügen , vorausgesetzt, der importierte Code versucht nicht, mehr Module zu importieren, während er verwendet wird.Wenn Ihr Top-Level-Modul keine Datei ist, sondern als Verzeichnis mit __init__.py gepackt ist, 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):
Ohne diese Zeile wird bei der Ausführung von exec_module versucht, relative Importe in Ihrer obersten Ebene __init__.py an den Modulnamen der obersten Ebene zu binden - in diesem Fall "mymodule". "Mymodule" ist jedoch noch nicht geladen, sodass die Fehlermeldung "SystemError: Übergeordnetes Modul 'mymodule' nicht geladen, relativer Import kann nicht ausgeführt werden" angezeigt wird. Sie müssen den Namen also binden, bevor Sie ihn laden. Der Grund dafür ist die grundlegende Invariante des relativen Importsystems: "Die invariante Position ist, dass Sie sys.modules ['spam'] und sys.modules ['spam.foo'] haben (wie Sie es nach dem obigen Import tun würden ) muss letzteres als foo-Attribut des ersteren erscheinen " wie hier diskutiert .
quelle
mymodule
?/path/to/your/module/
ist eigentlich/path/to/your/PACKAGE/
? und damitmymodule
meinst dumyfile.py
?Um Ihr Modul zu importieren, müssen Sie sein Verzeichnis vorübergehend oder dauerhaft zur Umgebungsvariablen hinzufügen.
Vorübergehend
Permanent
Hinzufügen der folgenden Zeile zu Ihrer
.bashrc
Datei (unter Linux) und Ausführensource ~/.bashrc
im Terminal:Kredit / Quelle: saarrrr , eine weitere Frage zum Stapelaustausch
quelle
Es hört sich so an, als ob Sie die Konfigurationsdatei nicht speziell importieren möchten (was viele Nebenwirkungen und zusätzliche Komplikationen mit sich bringt), sondern sie nur ausführen und auf den resultierenden Namespace zugreifen möchten. Die Standardbibliothek bietet eine spezielle API in Form von runpy.run_path :
Diese Schnittstelle ist in Python 2.7 und Python 3.2+ verfügbar
quelle
result[name]
,result.get('name', default_value)
etc)from runpy import run_path; from argparse import Namespace; mod = Namespace(**run_path('path/to/file.py'))
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".
Chaotisch, aber es funktioniert.
quelle
Du kannst den ... benutzen
Methode aus imp Modul .
quelle
imp.load_dynamic(module_name, path_to_file)
für DLLsquelle
except:
Sammelklausel ist selten eine gute Idee.save_cwd = os.getcwd()
try: …
finally: os.chdir(save_cwd)
this is already addressed by the standard library
Ja, aber Python hat die böse Angewohnheit, nicht abwärtskompatibel zu sein ... wie die überprüfte Antwort besagt, gibt es vor und nach 3.3 zwei verschiedene Möglichkeiten. In diesem Fall möchte ich lieber meine eigene universelle Funktion schreiben, als die Version im laufenden Betrieb zu überprüfen. Und ja, vielleicht ist dieser Code nicht allzu gut fehlergeschützt, aber er zeigt eine Idee (os.chdir (), über die ich noch nicht nachgedacht habe), auf deren Grundlage ich einen besseren Code schreiben kann. Daher +1.Hier ist ein Code, der in allen Python-Versionen von 2.7-3.5 und wahrscheinlich sogar in anderen funktioniert.
Ich habe es getestet. Es mag hässlich sein, aber bisher ist es das einzige, das in allen Versionen funktioniert.
quelle
load_source
nicht funktioniert, da sie das Skript importiert und dem Skript den Zugriff auf die Module und Globals zum Zeitpunkt des Imports ermöglicht.Ich habe eine leicht modifizierte Version von @ SebastianRittaus wunderbarer Antwort (für Python> 3.4, glaube ich) entwickelt, mit der Sie eine Datei mit einer beliebigen Erweiterung als Modul laden können,
spec_from_loader
anstattspec_from_file_location
:Der Vorteil der expliziten Codierung des Pfads
SourceFileLoader
besteht darin, dass die Maschine nicht versucht, den Dateityp aus der Erweiterung herauszufinden. Dies bedeutet, dass Sie.txt
mit dieser Methode so etwas wie eine Datei laden können , dies jedoch nichtspec_from_file_location
ohne Angabe des Loaders tun können, da dieser.txt
nicht vorhanden istimportlib.machinery.SOURCE_SUFFIXES
.quelle
Meinst du laden oder importieren?
Sie können die
sys.path
Liste bearbeiten, den Pfad zu Ihrem Modul angeben und dann Ihr Modul importieren. Beispiel: Ein Modul unter:Du könntest es tun:
quelle
sys.path[0:0] = ['/foo']
Explicit is better than implicit.
Warum also nichtsys.path.insert(0, ...)
stattsys.path[0:0]
?Ich glaube, Sie können das angegebene Modul verwenden
imp.find_module()
undimp.load_module()
laden. Sie müssen den Modulnamen vom Pfad trennen, dh wenn Sie laden/home/mypath/mymodule.py
möchten, müssen Sie Folgendes tun:... aber das sollte den Job erledigen.
quelle
Sie können das
pkgutil
Modul (insbesondere diewalk_packages
Methode) verwenden, um eine Liste der Pakete im aktuellen Verzeichnis abzurufen. Von dort aus ist es trivial, dieimportlib
gewünschten Module mithilfe der Maschinen zu importieren:quelle
Erstellen Sie das Python-Modul test.py
Erstellen Sie das Python-Modul test_check.py
Wir können das importierte Modul aus dem Modul importieren.
quelle
Dieser Bereich von Python 3.4 scheint äußerst schwierig zu verstehen zu sein! Mit ein bisschen Hacking mit dem Code von Chris Calloway als Anfang gelang es mir jedoch, etwas zum Laufen zu bringen. Hier ist die Grundfunktion.
Dies scheint nicht veraltete Module aus Python 3.4 zu verwenden. Ich gebe nicht vor zu verstehen warum, aber es scheint innerhalb eines Programms zu funktionieren. Ich fand, dass Chris 'Lösung in der Kommandozeile funktionierte, aber nicht innerhalb eines Programms.
quelle
Ich sage nicht, dass es besser ist, aber der Vollständigkeit halber wollte ich die
exec
Funktion vorschlagen , die sowohl in Python 2 als auch in Python 3 verfügbarexec
ist. Sie können beliebigen Code entweder im globalen Bereich oder in einem internen Bereich ausführen. als Wörterbuch zur Verfügung gestellt.Wenn Sie beispielsweise ein Modul in
"/path/to/module
"mit der Funktion gespeichert habenfoo()
, können Sie es folgendermaßen ausführen:Dies macht es etwas expliziter, dass Sie Code dynamisch laden, und gewährt Ihnen zusätzliche Leistung, z. B. die Möglichkeit, benutzerdefinierte integrierte Funktionen bereitzustellen.
Wenn Ihnen der Zugriff über Attribute anstelle von Schlüsseln wichtig ist, können Sie eine benutzerdefinierte Diktatklasse für die Globals entwerfen, die einen solchen Zugriff bietet, z.
quelle
Um ein Modul aus einem bestimmten Dateinamen zu importieren, können Sie den Pfad vorübergehend erweitern und den Systempfad in der Referenz für den endgültigen Block wiederherstellen :
quelle
Das sollte funktionieren
quelle
name, ext = os.path.splitext(os.path.basename(infile))
. Ihre Methode funktioniert aufgrund der vorherigen Einschränkung auf die Erweiterung .py. Außerdem sollten Sie das Modul wahrscheinlich in einen Variablen- / Wörterbucheintrag importieren.Wenn wir Skripte im selben Projekt haben, aber in verschiedenen Verzeichnissen, können wir dieses Problem mit der folgenden Methode lösen.
In dieser Situation
utils.py
ist insrc/main/util/
quelle
Ich habe ein Paket erstellt, das
imp
für Sie verwendet wird. Ich nenne esimport_file
und so wird es verwendet:Sie können es bekommen bei:
http://pypi.python.org/pypi/import_file
oder bei
http://code.google.com/p/import-file/
quelle
Paketmodule zur Laufzeit importieren (Python-Rezept)
http://code.activestate.com/recipes/223972/
quelle
Unter Linux funktioniert das Hinzufügen eines symbolischen Links in dem Verzeichnis, in dem sich Ihr Python-Skript befindet.
dh:
Python erstellt
/absolute/path/to/script/module.pyc
und aktualisiert es, wenn Sie den Inhalt von ändern/absolute/path/to/module/module.py
Fügen Sie dann Folgendes in mypythonscript.py ein
quelle
git
indem Sie Ihre verwenden und überprüfen,git status
um sicherzustellen, dass Ihre Änderungen am Skript tatsächlich zum Quelldokument zurückkehren und nicht im Äther verloren gehen.Ich habe meine eigene globale und tragbare Importfunktion basierend auf dem
importlib
Modul geschrieben für:sys.path
oder von einem beliebigen Suchpfadspeicher abhängig zu sein .Die Beispiele Verzeichnisstruktur:
Einschlussabhängigkeit und Reihenfolge:
Implementierung:
Speicher für neueste Änderungen: https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/python/tacklelib/tacklelib.py
test.py :
testlib.py :
testlib.std1.py :
testlib.std2.py :
testlib.std3.py :
Ausgabe (
3.7.4
):Getestet in Python
3.7.4
,3.2.5
,2.7.16
Vorteile :
testlib.std.py
astestlib
,testlib.blabla.py
astestlib_blabla
usw.).sys.path
oder einem beliebigen Suchpfadspeicher ab.SOURCE_FILE
undSOURCE_DIR
zwischen Aufrufen vontkl_import_module
.3.4.x
und höher] Kann die Modul-Namespaces in verschachteltentkl_import_module
Aufrufen mischen (z. B.named->local->named
oderlocal->named->local
so weiter).3.4.x
und höher] Kann globale Variablen / Funktionen / Klassen automatisch exportieren, von wo aus sie zu allen untergeordneten Modulen deklariert werden, die übertkl_import_module
(über dietkl_declare_global
Funktion) importiert wurden .Nachteile :
3.3.x
und niedriger] Erforderlich,tkl_import_module
in allen Modulen zu deklarieren, die aufrufentkl_import_module
(Codeduplizierung)Update 1,2 (nur für
3.4.x
und höher):In Python 3.4 und höher können Sie die Anforderung umgehen,
tkl_import_module
in jedem Modul zu deklarieren, indem Sietkl_import_module
in einem Modul der obersten Ebene deklarieren, und die Funktion würde sich in einem einzigen Aufruf auf alle untergeordneten Module auswirken (dies ist eine Art Selbstbereitstellungsimport).Update 3 :
Funktion
tkl_source_module
als analog zu Bashsource
mit Support Execution Guard beim Import hinzugefügt (implementiert durch die Modulzusammenführung anstelle des Imports).Update 4 :
Funktion
tkl_declare_global
zum automatischen Exportieren einer globalen Modulvariablen in alle untergeordneten Module hinzugefügt, in denen eine globale Modulvariable nicht sichtbar ist, da sie nicht Teil eines untergeordneten Moduls ist.Update 5 :
Alle Funktionen wurden in die Tacklelib-Bibliothek verschoben, siehe den obigen Link.
quelle
Es gibt ein spezielles Paket :
Es wurde in allen Python-Versionen getestet (auch Jython und PyPy), kann jedoch je nach Größe Ihres Projekts zu viel des Guten sein.
quelle
Hinzufügen dieser zur Liste der Antworten, da ich nichts finden konnte, was funktionierte. Dies ermöglicht den Import kompilierter (pyd) Python-Module in 3.4:
quelle
Ganz einfache Möglichkeit: Angenommen, Sie möchten eine Datei mit dem relativen Pfad importieren. / .. / MyLibs / pyfunc.py
Aber wenn Sie es ohne Wache schaffen, können Sie endlich einen sehr langen Weg zurücklegen
quelle
Eine einfache Lösung
importlib
anstelle desimp
Pakets (getestet für Python 2.7, obwohl es auch für Python 3 funktionieren sollte):Jetzt können Sie den Namespace des importierten Moduls direkt wie folgt verwenden:
Der Vorteil dieser Lösung ist, dass wir nicht einmal den tatsächlichen Namen des Moduls kennen müssen, das wir importieren möchten , um es in unserem Code zu verwenden. Dies ist nützlich, z. B. wenn der Pfad des Moduls ein konfigurierbares Argument ist.
quelle
sys.path
, was nicht für jeden Anwendungsfall geeignet ist.sys.path.pop()
Diese Antwort ist eine Ergänzung zu Sebastian Rittaus Antwort auf den Kommentar: "Aber was ist, wenn Sie den Modulnamen nicht haben?" Dies ist eine schnelle und schmutzige Methode, um den wahrscheinlichen Namen des Python-Moduls mit einem Dateinamen zu versehen. Er geht nur den Baum hoch, bis ein Verzeichnis ohne
__init__.py
Datei gefunden wird, und wandelt es dann wieder in einen Dateinamen um. Für Python 3.4+ (verwendet pathlib) ist dies sinnvoll, da Py2-Benutzer "imp" oder andere Methoden für relative Importe verwenden können:Es gibt sicherlich Verbesserungsmöglichkeiten, und die optionalen
__init__.py
Dateien erfordern möglicherweise andere Änderungen, aber wenn Sie__init__.py
im Allgemeinen haben, ist dies der Trick.quelle
Ich denke, der beste Weg ist aus der offiziellen Dokumentation ( 29.1. Imp - Zugriff auf die Import-Interna ):
quelle