Wie importiere ich ein Python-Modul anhand seines relativen Pfads?
Wenn beispielsweise dirFoo
enthält Foo.py
und dirBar
, und dirBar
enthält Bar.py
, wie importiere ich Bar.py
in Foo.py
?
Hier ist eine visuelle Darstellung:
dirFoo\
Foo.py
dirBar\
Bar.py
Foo
möchte einbeziehen Bar
, aber eine Umstrukturierung der Ordnerhierarchie ist keine Option.
python
relative-path
python-import
Jude Allred
quelle
quelle
Antworten:
Angenommen, Ihre beiden Verzeichnisse sind echte Python-Pakete (enthalten die
__init__.py
Datei), ist hier eine sichere Lösung für die Aufnahme von Modulen relativ zum Speicherort des Skripts.Ich gehe davon aus, dass Sie dies tun möchten, da Sie Ihrem Skript eine Reihe von Modulen hinzufügen müssen. Ich verwende dies in der Produktion in mehreren Produkten und arbeite in vielen speziellen Szenarien wie: Skripten, die aus einem anderen Verzeichnis aufgerufen oder mit Python Execute ausgeführt werden, anstatt einen neuen Interpreter zu öffnen.
Als Bonus können Sie mit diesem Ansatz Python zwingen, Ihr Modul anstelle der auf dem System installierten zu verwenden.
Warnung! Ich weiß nicht wirklich, was passiert, wenn sich das aktuelle Modul in einer
egg
Datei befindet. Es scheitert wahrscheinlich auch.quelle
os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]) + "/subfolder")
Do NOT den Unterordner hinzufügen , bevorabspath
da dies schwerwiegende Fehler verursacht.cmd_subfolder
) gerne direkt zu meiner Antwort hinzufügen . Vielen Dank!realpath
schon absolute pfade, die ich also nicht braucheabspath
. Auchos.path.dirname
kann anstelle von Split verwendet werden, makeing die Indizierung[0]
obsolet. Die Linie wäre dann:os.path.realpath(os.path.dirname(inspect.getfile(inspect.currentframe())))
Stellen Sie sicher, dass dirBar die
__init__.py
Datei hat - dies macht ein Verzeichnis zu einem Python-Paket.quelle
sys.path
das Vorhandensein von__init__.py
imdirBar
Verzeichnis nicht viel.__init.py__
funktioniert nur, wenn sich das Verzeichnis bereits in sys.path befindet und in meinem Fall nicht. Die Lösung von "sorin" (akzeptiert) funktioniert immer.sys.path
der Frage enthalten ist? Vielleicht wurde etwas ausgelassen, von dem wir nichts gesehen oder gewusst haben?Sie können das Unterverzeichnis auch Ihrem Python-Pfad hinzufügen, damit es als normales Skript importiert wird.
quelle
sys.path.append(os.path.dirname(__file__) + "/relative/path/to/module")
sys.path.append(__name__ if __name__ != '__main__' else __loader__.fullname)
sys.path.insert(0, <path to dirFoo>)
da dieses Modul vor den an anderer Stelle gespeicherten gleichnamigen Modulen geladen wird.quelle
os.path.join()
anstelle von '/' verwenden, wodurch die (lahmen) Fenster unterbrochen werden.os.path.abspath(os.path.join(__file__,'..','lib'))
?Führen Sie einfach einfache Schritte aus, um die .py-Datei aus einem anderen Ordner zu importieren.
Angenommen, Sie haben ein Verzeichnis wie:
Bewahren Sie dann einfach eine leere Datei wie angegeben im lib-Ordner auf
Und dann benutzen
Bewahren Sie die
__init__.py
Datei in jedem Ordner der Hierarchie des Importmoduls auf.quelle
Wenn Sie Ihr Projekt folgendermaßen strukturieren:
Dann sollten Sie von Foo.py aus in der Lage sein:
Oder:
Laut Toms Kommentar muss der
src
Ordner entweder übersite_packages
oder über Ihren Suchpfad zugänglich sein . Außerdem wird, wie er erwähnt,__init__.py
implizit importiert, wenn Sie zum ersten Mal ein Modul in dieses Paket / Verzeichnis importieren. In der Regel__init__.py
ist einfach eine leere Datei.quelle
from dirFoo import Foo
zu sagenFoo.bla()
. Bei Verwendungimport dirFoo.Foo
sollte man verwendendirFoo.Foo.bla()
- ziemlich hässlich auch ohne Kamelkoffer.Die einfachste Methode ist die Verwendung von sys.path.append ().
Möglicherweise interessieren Sie sich aber auch für das imp- Modul. Es bietet Zugriff auf interne Importfunktionen.
Dies kann verwendet werden, um Module dynamisch zu laden, wenn Sie den Namen eines Moduls nicht kennen.
Ich habe dies in der Vergangenheit verwendet, um eine Plugin-Schnittstelle für eine Anwendung zu erstellen, in der der Benutzer ein Skript mit anwendungsspezifischen Funktionen schreibt und das Skript einfach in einem bestimmten Verzeichnis ablegt.
Diese Funktionen können auch nützlich sein:
quelle
Dies ist der relevante PEP:
http://www.python.org/dev/peps/pep-0328/
Angenommen, dirFoo ist ein Verzeichnis von dirBar ...
In dirFoo \ Foo.py:
quelle
Der einfachste Weg, ohne Änderungen an Ihrem Skript vorzunehmen, besteht darin, die Umgebungsvariable PYTHONPATH festzulegen. Weil sys.path von folgenden Speicherorten aus initialisiert wird:
Renn einfach:
Ihr sys.path enthält den obigen Pfad, wie unten gezeigt:
quelle
Meiner Meinung nach ist es die beste Wahl, __ init __.py in den Ordner zu legen und die Datei mit aufzurufen
Es wird nicht empfohlen, sys.path.append () zu verwenden, da möglicherweise ein Fehler auftritt, wenn Sie denselben Dateinamen wie das vorhandene Python-Paket verwenden. Ich habe das nicht getestet, aber das wird nicht eindeutig sein.
quelle
from dirBar.Bar import *
funktioniert aber nichtfrom dirBar.Bar import Bar
. Weißt du warum * funktioniert? Was wäre, wenn ich mehrere Dateien in dirBar / hätte und nur einige davon abrufen wollte (mit einer Methode wie der, die Sie hier gepostet haben)?from dirBar import Bar
.from
die Quelle angibt und alles, was danachimport
kommt, was von dieser Quelle zu holen ist.from dirBar.Bar import Bar
bedeutet "Aus der Quelle die Quelle selbst importieren", was keinen Sinn ergibt. das*
obwohl bedeutet, "gib mir alles von der Quelle"Der schnelle und schmutzige Weg für Linux-Benutzer
Wenn Sie nur herumspielen und sich nicht um Bereitstellungsprobleme kümmern, können Sie einen symbolischen Link verwenden (vorausgesetzt, Ihr Dateisystem unterstützt dies), um das Modul oder Paket direkt im Ordner des anfordernden Moduls sichtbar zu machen.
oder
Hinweis: Ein "Modul" ist eine beliebige Datei mit der Erweiterung .py und ein "Paket" ist ein beliebiger Ordner, der die Datei enthält
__init__.py
(dies kann eine leere Datei sein). Unter dem Gesichtspunkt der Verwendung sind Module und Pakete identisch - beide legen ihre enthaltenen "Definitionen und Anweisungen" offen, wie über denimport
Befehl angefordert .Siehe: http://docs.python.org/2/tutorial/modules.html
quelle
anstatt:
Nur für den Fall, dass eine andere dirBar installiert sein könnte und einen foo.py-Reader verwirren könnte.
quelle
Um in diesem Fall Bar.py in Foo.py zu importieren, würde ich diese Ordner zunächst wie folgt in Python-Pakete umwandeln:
Dann würde ich es so in Foo.py machen:
Wenn ich wollte, dass der Namespace wie Bar aussieht. was auch immer oder
Wenn ich den Namespace dirBar.Bar haben wollte. was auch immer . Dieser zweite Fall ist nützlich, wenn Sie mehr Module unter dem dirBar-Paket haben.
quelle
Fügen Sie eine __init__.py- Datei hinzu:
Fügen Sie dann diesen Code zum Start von Foo.py hinzu:
quelle
dirBar
es sich bereits um ein Python-Paket handelt (aufgrund der Existenz vondirBar/__init__.py
), müssen Sie es nicht anhängendirBar
,sys.path
oder? Die Aussageimport Bar
vonFoo.py
sollte ausreichen.Beispiel für einen relativen sys.path:
Basierend auf dieser Antwort.
quelle
Wie Sie bereits erwähnt haben, möchten Sie normalerweise Zugriff auf einen Ordner mit Ihren Modulen haben, der sich darauf bezieht, wo Ihr Hauptskript ausgeführt wird. Sie importieren sie also einfach.
Lösung:
Ich habe das Skript
D:/Books/MyBooks.py
und einige Module (wie oldies.py). Ich muss aus dem Unterverzeichnis importierenD:/Books/includes
:Platzieren Sie ein
print('done')
inoldies.py
, damit Sie überprüfen, ob alles in Ordnung ist. Diese Methode funktioniert immer, da nach der Python-Definition,sys.path
die beim Programmstart initialisiert wurde, das erste Element dieser Listepath[0]
das Verzeichnis ist, das das Skript enthält, mit dem der Python-Interpreter aufgerufen wurde.Wenn das Skriptverzeichnis nicht verfügbar ist (z. B. wenn der Interpreter interaktiv aufgerufen wird oder wenn das Skript aus der Standardeingabe gelesen wird),
path[0]
ist dies die leere Zeichenfolge, die Python anweist, zuerst die Module im aktuellen Verzeichnis zu suchen. Beachten Sie, dass das Skriptverzeichnis vor den Einträgen eingefügt wird, die als Ergebnis von eingefügt wurdenPYTHONPATH
.quelle
site.addsitedir(sys.path[0]+'/includes')
In meinem ersten einfachen Python-Programm break_time.py musste ich einen Schrägstrich anstelle von zwei umgekehrten Schrägstrichen (dh ) verwenden: https://github.com/ltfschoen/PythonTest . Ich benutze System: MacOS 10.11.5, Python 2.7.12, IDLE IDE 2.7.12, Tk 8.5.9Einfach können Sie verwenden:
from Desktop.filename import something
Beispiel:
der Code:
Stellen Sie jedoch sicher, dass Sie
__init__.py
in diesem Verzeichnis eine leere Datei mit dem Namen " " erstellenquelle
import something
dann sagte ich, es einfacher zu machen, es ist*
nicht gut für RAM und auch wenn 2 Funktionen den gleichen Namen haben, wird es Ihren Code zusammenfassenEine andere Lösung wäre, das py-require- Paket zu installieren und dann das Folgende in zu verwenden
Foo.py
quelle
require()
Funktion benötigen , können Sie sich mein Node.py-Projekt ansehen: github.com/nodepy/nodepyHier ist eine Möglichkeit, eine Datei von einer Ebene über dem relativen Pfad zu importieren.
Verschieben Sie das Arbeitsverzeichnis einfach um eine Ebene (oder einen beliebigen relativen Speicherort) nach oben, fügen Sie es Ihrem Pfad hinzu und verschieben Sie das Arbeitsverzeichnis wieder dorthin, wo es begonnen hat.
quelle
Ich habe keine Erfahrung mit Python. Wenn meine Worte falsch sind, sag es mir einfach. Wenn Ihre Dateihierarchie so angeordnet ist:
module_1.py
definiert eine Funktion aufgerufenfunc_1()
, module_2.py :und wenn Sie
python module_2.py
in cmd ausführen , wird ausgeführt, wasfunc_1()
definiert ist. So importieren wir normalerweise dieselben Hierarchiedateien. Aber wenn Sie schreibenfrom .module_1 import func_1
inmodule_2.py
, wird Python - Interpreter sagenNo module named '__main__.module_1'; '__main__' is not a package
. Um dies zu beheben, behalten wir einfach die Änderung bei, die wir gerade vorgenommen haben, und verschieben beide Module in ein Paket und lassen ein drittes Modul als Aufrufer ausführenmodule_2.py
.main.py :
Aber der Grund , warum wir eine hinzufügen ,
.
bevormodule_1
inmodule_2.py
ist , dass , wenn wir nicht tun , dass und ausführenmain.py
, wird Python - Interpreter sagenNo module named 'module_1'
, dass ein wenig kompliziert ist,module_1.py
ist direkt nebenmodule_2.py
. Nun lasse ichfunc_1()
inmodule_1.py
do etwas:das
__name__
zeichnet auf, wer func_1 aufruft. Jetzt behalten wir das.
vorhermodule_1
, laufenmain.py
, es wird gedrucktpackage_1.module_1
, nichtmodule_1
. Es zeigt an, dass sich derjenige, der anruft,func_1()
in derselben Hierarchie wie befindetmain.py
, was.
bedeutet, dass ermodule_1
sich in derselben Hierarchie wie ermodule_2.py
selbst befindet. Wenn es also keinen Punkt gibt,main.py
dermodule_1
an derselben Hierarchie wie er selbst erkennt, kann er erkennenpackage_1
, , aber nicht, was "darunter" ist.Lassen Sie es uns jetzt etwas komplizierter machen. Sie haben ein
config.ini
und ein Modul definiert eine Funktion zum Lesen in derselben Hierarchie wie 'main.py'.Und aus irgendeinem unvermeidlichen Grund muss man es mit aufrufen
module_2.py
, damit es aus der oberen Hierarchie importiert werden kann. module_2.py :Zwei Punkte bedeuten den Import aus der oberen Hierarchie (drei Punkte greifen auf die oberen als die oberen usw. zu). Jetzt rennen wir
main.py
, der Dolmetscher wird sagen :ValueError:attempted relative import beyond top-level package
. Das "Top-Level-Paket" hier istmain.py
. Nur weil sieconfig.py
daneben liegenmain.py
, befinden sie sich in derselben Hierarchie,config.py
sind nicht "unter"main.py
oder werden nicht "angeführt"main.py
, also ist es jenseitsmain.py
. Um dies zu beheben, ist der einfachste Weg:Ich denke, das stimmt mit dem Prinzip der Anordnung der Projektdateihierarchie überein. Sie sollten Module mit unterschiedlichen Funktionen in verschiedenen Ordnern anordnen und nur einen Top-Aufrufer im Freien lassen, und Sie können importieren, wie immer Sie wollen.
quelle
Dies funktioniert auch und ist viel einfacher als alles andere mit dem
sys
Modul:quelle
Rufen Sie mich übermäßig vorsichtig an, aber ich mache meine gerne portabler, weil es unsicher ist anzunehmen, dass sich Dateien auf jedem Computer immer an derselben Stelle befinden. Persönlich muss der Code zuerst den Dateipfad nachschlagen. Ich benutze Linux, damit meine so aussehen würde:
Das ist natürlich so, es sei denn, Sie planen, diese zusammen zu verpacken. Aber wenn das der Fall ist, brauchen Sie sowieso nicht wirklich zwei separate Dateien.
quelle