Wie zu tun, relative Importe in Python?
Vorstellen, diese Verzeichnisstruktur:
app/
__init__.py
sub1/
__init__.py
mod1.py
sub2/
__init__.py
mod2.py
Ich bin Codierung mod1
, und ich importieren müssen etwas aus mod2
. Wie sollte ich es tun?
Versuchte ich from ..sub2 import mod2
aber ich bin immer ein "Versuch der relative import in nicht-Paket".
Googelte ich herum, fand aber nur "sys.path
manipulation" hacks. Gibt es da nicht eine saubere Art und Weise?
Edit: alle meine __init__.py
's sind derzeit leer
Edit2: ich bin versucht, das zu tun, weil sub2 enthält Klassen, die in sub-Pakete ( sub1
, subX
usw.).
Edit3: Das Verhalten, das ich Suche, ist die gleiche wie im PEP 366 (Dank John B)
Ich empfehle die Aktualisierung Ihrer Frage zu machen, mehr klar, dass Sie beschreiben das Thema PEP 366.
Es ist eine langatmige Erklärung, aber prüfen Sie hier: stackoverflow.com/a/10713254/1267156, antwortete ich eine sehr ähnliche Frage. Ich hatte das gleiche problem, bis Letzte Nacht.
Für diejenigen, die wollen, um ein Modul laden befindet sich an einer beliebigen Pfad, siehe: stackoverflow.com/questions/67631/...
Auf einem verwandten beachten, Python 3 wird es ändern die Standard-Handhabung von Importen zu werden absolute standardmäßig; relative Importe müssen explizit angegeben werden.
Es ist eine langatmige Erklärung, aber prüfen Sie hier: stackoverflow.com/a/10713254/1267156, antwortete ich eine sehr ähnliche Frage. Ich hatte das gleiche problem, bis Letzte Nacht.
Für diejenigen, die wollen, um ein Modul laden befindet sich an einer beliebigen Pfad, siehe: stackoverflow.com/questions/67631/...
Auf einem verwandten beachten, Python 3 wird es ändern die Standard-Handhabung von Importen zu werden absolute standardmäßig; relative Importe müssen explizit angegeben werden.
InformationsquelleAutor Joril | 2008-09-16
Du musst angemeldet sein, um einen Kommentar abzugeben.
Jeder scheint zu wollen, sagen Ihnen, was Sie tun sollte, anstatt einfach die Frage zu beantworten.
Das problem ist, dass Sie das Modul als '__main__' durch die übergabe der mod1.py als ein argument an den interpreter.
Vom PEP 328:
In Python 2.6, Sie sind das hinzufügen der Möglichkeit zum Bezug der Module relativ zu dem Haupt-Modul. PEP 366 beschreibt die Veränderung.
Update: Nach Nick Coghlan, die empfohlene alternative ist das Modul ausführen, das im Paket mit den-m Schalter.
Die empfohlene alternative ist, laufen die Module in Paketen mit der
-m
wechseln, anstatt durch die Angabe von Dateinamen direkt.Ich verstehe nicht: wo ist hier die Antwort? Wie kann man import-Module in einen solchen Verzeichnis-Struktur???
In diesem Fall mod1 würde
from sub2 import mod2
. Dann laufen mod1, von innerhalb der app tunpython -m sub1.mod1
.bedeutet das, dass Sie nicht tun können, wenn Ihre python ist in eine Anwendung eingebettet, so dass Sie nicht haben Zugriff auf python-Befehlszeilen-Schalter?
InformationsquelleAutor John B
python main.py
.main.py
hat:import app.package_a.module_a
module_a.py
hatimport app.package_b.module_b
Wahlweise 2 oder 3 könnten:
from app.package_a import module_a
Dass wird funktionieren, solange Sie
app
in deinem PYTHONPATH.main.py
könnte überall sein dann.So schreiben Sie eine
setup.py
zu kopieren (installieren) der gesamten app-Paket und Unterpakete, die an das target-system der python-Ordner und dermain.py
Ziel system script-Ordner.Weiterführende Literatur: blog.habnab.it/blog/2013/07/21/python-Pakete-und-dich
dann, eines Tages, müssen ändern Sie den Namen der app zu test_app. was würde dann passieren? Sie wird sich ändern müssen alle source-codes, importieren app.package_b.module_b --> test_app.package_b.module_b. dies ist absolut SCHLECHTE Praxis... Und wir sollten versuchen, relative import in das Paket.
InformationsquelleAutor nosklo
Hier ist die Lösung die für mich funktioniert:
Ich die relative Importe als
from ..sub2 import mod2
und dann, wenn ich Sie ausführen möchten
mod1.py
dann gehe ich in das übergeordnete Verzeichnis vonapp
und führen Sie das Modul mit Hilfe der python -m-Schalter alspython -m app.sub1.mod1
.Den wahren Grund, warum dieses problem tritt auf, mit relativ importiert, ist, dass die relative Importe funktioniert, indem die
__name__
Eigenschaft des Moduls. Wenn das Modul direkt gestartet, dann__name__
eingestellt ist__main__
und es enthält keine Informationen über Paket-Struktur. Und, das ist, warum python beschwert sich über dierelative import in non-package
Fehler.So, indem Sie den-m-Schalter stellen Sie die Paket-Struktur Informationen zu python, durch die es beheben kann, relativ erfolgreich importiert wurde.
Habe ich auf dieses problem viele Male, während Sie relative Importe. Und, nach der Lektüre all die bisherigen Antworten, ich war noch nicht in der Lage, herauszufinden, wie es zu lösen, in eine saubere Art und Weise, ohne sich zu setzen boilerplate-code in allen Dateien. (Obwohl einige der Kommentare waren wirklich hilfreich, vielen Dank an @ncoghlan und @XiongChiamiov)
Hoffe, dies hilft jemand, ist der Kampf mit der relativen Importe problem, weil die Fahrt durch PEP ist wirklich kein Spaß.
-m
wurde entwickelt, um zu lösen.Beachten Sie auch: diese Antwort war 5 Jahre nach der Frage. Diese Funktionen waren nicht verfügbar zur Zeit.
Wenn Sie möchten, importieren Sie ein Modul aus dem gleichen Verzeichnis, die Sie tun können
from . import some_module
.InformationsquelleAutor Pankaj
"Guido Ansichten die Ausführung von Skripts, die in einem Paket als ein anti-pattern" (abgelehnt
PEP-3122)
Habe ich verbrachte so viel Zeit versucht, eine Lösung zu finden, Lesen related posts hier auf Stack Overflow und sagte mir "es muss einen besseren Weg geben!". Sieht aus wie es ist nicht.
-m
Schalter:python -m app.sub1.mod1
oder rufen Sieapp.sub1.mod1.main()
von einem top-level-Skript (z.B. generiert aus den setuptools' entry_points definiert setup.py).InformationsquelleAutor lesnik
Dieses Problem ist 100%:
Importieren settings/local_setting.py in app/main.py:
main.py:
sys.path.insert(0, "../settings")
und dannfrom local_settings import *
InformationsquelleAutor Роман Арсеньев
Ich bin mit diesem snippet zu importieren Module aus dem Wege, hoffe, das hilft
Wahrscheinlich, sys.Pfad.append(Pfad) sollte ersetzt werden durch sys.Pfad.insert(0, Pfad), und sys.Pfad[-1] ersetzt werden sollte mit dem sys.Pfad[0]. Sonst ist die Funktion importieren das falsche Modul, wenn es bereits ein Modul mit dem gleichen Namen in den Suchpfad. E. g., wenn es ist "some.py" im aktuellen Verzeichnis, import_path("/imports/some.py") importieren Sie die falsche Datei.
Ich bin damit einverstanden! Manchmal werden auch andere relative Importe machen precedance. Verwenden Sie sys.Pfad.einfügen
Wie würden Sie replizieren das Verhalten von x import y (oder *)?
Es ist nicht klar, geben Sie bitte die vollständige Verwendung dieses Skripts zu lösen, OP-problem.
InformationsquelleAutor iElectric
Erklärung
nosklo's
Antwort mit BeispielenHinweis: alle
__init__.py
Dateien sind leer.app/package_a/fun_a.py
app/package_b/fun_b.py
main.py
wenn Sie
$ python main.py
es gibt:from app.package_b import fun_b
from app.package_a.fun_a import print_a
so-Datei im Ordner
package_b
verwendet-Datei im Ordnerpackage_a
, das ist, was Sie wollen. Recht????InformationsquelleAutor suhailvs
Dies ist leider ein sys.Pfad hack, aber es funktioniert ganz gut.
Ich traf dieses problem mit einer anderen Ebene: ich hatte bereits ein Modul mit dem angegebenen Namen, aber es war das falsche Modul.
was ich tun wollte war Folgendes (das Modul war ich arbeiten war, modul3):
Hinweis, dass ich bereits installiert mymodule gesucht, aber in meiner installation habe ich nicht "mymodule1"
und ich würde um eine ImportError, weil es versuchte, den import von meinen installierten Modulen.
Ich versucht habe eine sys.Pfad.Anhängen, und das hat nicht funktioniert. Was funktioniert hat war ein sys.Pfad.legen Sie
So eine Art hack, aber habe Sie alle an die Arbeit!
So halten Sie im Verstand, wenn Sie wollen, Ihre Entscheidung zu überschreiben, andere Wege dann müssen Sie nur noch sys.Pfad.insert(0, Pfadname) zum laufen bekommen! Dies war eine sehr frustrierende Knackpunkt für mich, Zut von Menschen, die sagen, die "append" - Funktion sys.Weg, aber das funktioniert nicht, wenn Sie bereits ein Modul definiert (ich finde es sehr merkwürdig Verhalten)
sys.path.append('../')
funktioniert gut für mich (Python 3.5.2)Ich denke, das ist in Ordnung, da es lokalisiert den hack, um die ausführbare Datei und hat keine Auswirkungen auf andere Module, die das können, hängt von Ihrer Pakete.
InformationsquelleAutor Garrett Berg
Lassen Sie mich nur das hier für meine eigene Referenz. Ich weiß, dass es nicht gut ist, Python-code, aber ich bräuchte einen Skript für ein Projekt an dem ich arbeitete, und ich wollte das Skript in einer
scripts
Verzeichnis.InformationsquelleAutor milkypostman
Als @EvgeniSergeev sagt in den Kommentaren zu der OP, können Sie importieren von code aus einem
.py
- Datei an eine beliebige Position mit:Aus diese SO beantworten.
InformationsquelleAutor LondonRob
Werfen Sie einen Blick auf http://docs.python.org/whatsnew/2.5.html#pep-328-absolute-and-relative-imports. Sie konnte tun
InformationsquelleAutor mossplix
Vom Python-doc,
InformationsquelleAutor jung rhew
Fand ich es eher leicht "PYTHONPATH" enviroment-variable auf den obersten Ordner:
dann:
natürlich PYTHONPATH ist "global", aber es hob nicht Mühe für mich noch.
virtualenv
verwalten Sie Ihre import-Anweisungen.InformationsquelleAutor Andrew_1510
Am Anfang dessen, was John B sagte, es scheint, wie die Einstellung der
__package__
variable sollte helfen, anstatt Sie zu verändern__main__
was vermasseln könnte andere Dinge. Aber soweit ich das testen konnte, ist es nicht ganz so funktionieren, wie es sollte.Ich habe das gleiche problem und weder PEP 328 oder 366 lösen das problem vollständig, wie beide, von der Ende des Tages, muss der Kopf des Pakets enthalten
sys.path
, soweit ich Sie verstehen konnte.Sollte ich auch erwähnen, dass ich nicht finden, wie format der string, der sollte in die Variablen. Ist es
"package_head.subfolder.module_name"
oder was?InformationsquelleAutor Gabriel
Angenommen, Sie starten auf der obersten Ebene, dann in
mod1
verwenden:statt
InformationsquelleAutor lukmac