Ich möchte von einer Klasse in einer Datei erben, die sich in einem Verzeichnis über dem aktuellen befindet.
Ist es möglich, diese Datei relativ zu importieren?
quelle
Ich möchte von einer Klasse in einer Datei erben, die sich in einem Verzeichnis über dem aktuellen befindet.
Ist es möglich, diese Datei relativ zu importieren?
from ..subpkg2 import mod
Gemäß den Python-Dokumenten: Verwenden Sie in einer Pakethierarchie zwei Punkte, wie im Dokument mit den Importanweisungen angegeben :
Wenn Sie angeben, welches Modul importiert werden soll, müssen Sie nicht den absoluten Namen des Moduls angeben. Wenn ein Modul oder Paket in einem anderen Paket enthalten ist, ist es möglich, einen relativen Import innerhalb desselben Top-Pakets durchzuführen, ohne den Paketnamen angeben zu müssen. Durch die Verwendung führender Punkte im angegebenen Modul oder Paket
from
können Sie festlegen, wie hoch die aktuelle Pakethierarchie durchlaufen werden soll, ohne genaue Namen anzugeben. Ein führender Punkt bedeutet das aktuelle Paket, in dem das Modul existiert, das den Import vornimmt. Zwei Punkte bedeuten eine Paketebene . Drei Punkte sind zwei Ebenen höher. Wenn Sie alsofrom . import mod
von einem Modul impkg
Paket aus ausführen, werden Sie am Ende importierenpkg.mod
. Wenn Siefrom ..subpkg2 import mod
von innen ausführen, werdenpkg.subpkg1
Sie importierenpkg.subpkg2.mod
. Die Spezifikation für relative Importe ist in PEP 328 enthalten .
PEP 328 befasst sich mit absoluten / relativen Importen.
quelle
Die Antwort von @ gimel ist richtig, wenn Sie die von ihm erwähnte Pakethierarchie garantieren können. Wenn Sie nicht können - wenn Ihr wirklicher Bedarf so ist, wie Sie ihn ausgedrückt haben, ausschließlich an Verzeichnisse gebunden ist und keine notwendige Beziehung zur Verpackung besteht -, müssen Sie daran arbeiten
__file__
, das übergeordnete Verzeichnis herauszufinden (ein paaros.path.dirname
Aufrufe reichen aus; -), dann (wenn das Verzeichnis nicht bereits eingeschaltet istsys.path
) prepend vorübergehend den Einsatz dir gleich am Anfang vonsys.path
,__import__
, sagte Entfernen dir wieder - chaotisch Arbeit in der Tat, aber, „wenn es sein muss, müssen Sie“ (und Pyhon ist bestrebt, nie den Programmierer aufhören zu tun , was muss getan werden - ebenso wie die Norm ISO C sagt in der „Spirit of C“ in seinem Vorwort -!).Hier ist ein Beispiel, das für Sie funktionieren könnte:
quelle
sys.path
um dasselbe Modul unter verschiedenen Namen und allen entsprechenden Fehlern verfügbar zu machen. autopath.py in pypy oder _preamble.py in twisted lösen es mithilfe eines Suchkriteriums, das das Paket der obersten Ebene identifiziert, während die Verzeichnisse nach oben durchlaufen werden.sys.path.remove(pathYouJustAdded)
nach dem Import etwas tun, das Sie benötigen, um diesen neuen Pfad nicht beizubehalten.Importieren Sie das Modul aus einem Verzeichnis, das genau eine Ebene über dem aktuellen Verzeichnis liegt:
quelle
from .. import module
Ich habe einen Fehler erhalten ValueError: Versucht, relativen Import in Nicht-Paket durchSo laden Sie ein Modul, das ein Verzeichnis ist
Vorwort: Ich habe eine frühere Antwort grundlegend umgeschrieben, in der Hoffnung, den Menschen den Einstieg in das Python-Ökosystem zu erleichtern und hoffentlich allen die beste Änderung des Erfolgs mit dem Python-Importsystem zu ermöglichen.
Dies wird relative Importe innerhalb eines Pakets abdecken , was meiner Meinung nach der wahrscheinlichste Fall für die Frage von OP ist.
Python ist ein modulares System
Aus diesem Grund schreiben wir,
import foo
um ein Modul "foo" aus dem Root-Namespace zu laden, anstatt zu schreiben:Python ist nicht an ein Dateisystem gekoppelt
Aus diesem Grund können wir Python in Umgebungen einbetten, in denen es kein defacto-Dateisystem gibt, ohne ein virtuelles wie Jython bereitzustellen.
Durch die Entkopplung von einem Dateisystem können Importe flexibel durchgeführt werden. Dieses Design ermöglicht beispielsweise Importe aus Archiv- / Zip-Dateien, Import-Singletons, Bytecode-Caching, CFFI-Erweiterungen und sogar das Laden von Remote-Codedefinitionen.
Wenn Importe also nicht an ein Dateisystem gekoppelt sind, was bedeutet "ein Verzeichnis hoch"? Wir müssen einige Heuristiken auswählen, aber wir können dies tun, zum Beispiel wenn wir innerhalb eines Pakets arbeiten . Einige wurden bereits definiert, die relative Importe wie
.foo
und..foo
innerhalb desselben Pakets funktionieren lassen. Cool!Wenn Sie Ihre Quellcode-Lademuster aufrichtig mit einem Dateisystem koppeln möchten, können Sie dies tun. Sie müssen Ihre eigenen Heuristiken auswählen und eine Art Importmaschine verwenden. Ich empfehle importlib
Das Importlib-Beispiel von Python sieht ungefähr so aus:
Verpackung
Ein großartiges Beispielprojekt ist offiziell hier verfügbar: https://github.com/pypa/sampleproject
Ein Python-Paket ist eine Sammlung von Informationen zu Ihrem Quellcode, die andere Tools darüber informieren können, wie Sie Ihren Quellcode auf andere Computer kopieren und Ihren Quellcode in den Pfad dieses Systems integrieren, damit er
import foo
für andere Computer funktioniert (unabhängig vom Interpreter). Host-Betriebssystem usw.)Verzeichnisaufbau
Lassen Sie uns
foo
in einem Verzeichnis einen Paketnamen haben (vorzugsweise in einem leeren Verzeichnis).Ich bevorzuge es,
setup.py
als Geschwister zu erstellenfoo.py
, da dies das Schreiben der Datei setup.py vereinfacht. Sie können jedoch eine Konfiguration schreiben, um alles zu ändern / umzuleiten, was setuptools standardmäßig tut, wenn Sie möchten. Zum Beispiel ist das Einfügenfoo.py
in ein "src /" - Verzeichnis etwas populär, das hier nicht behandelt wird..
.
"editierbar" aka
-e
wird die Importmaschinerie erneut umleiten, um die Quelldateien in dieses Verzeichnis zu laden, und stattdessen die aktuellen genauen Dateien in die Bibliothek der Installationsumgebung kopieren. Dies kann auch zu Verhaltensunterschieden auf dem Computer eines Entwicklers führen. Testen Sie unbedingt Ihren Code! Es gibt andere Tools als pip, aber ich würde pip als Einführung empfehlen :)Ich möchte auch
foo
ein "Paket" (ein Verzeichnis mit__init__.py
) anstelle eines Moduls (eine einzelne ".py" -Datei) erstellen. Sowohl "Pakete" als auch "Module" können in den Root-Namespace geladen werden. Module ermöglichen verschachtelte Namespaces. Dies ist hilfreich, wenn ein Import von "relativ einem Verzeichnis" gewünscht wird..
Ich mache auch gerne ein
foo/__main__.py
, dies ermöglicht Python, das Paket als Modulpython3 -m foo
auszuführen , zB wird ausgeführtfoo/__main__.py
als__main__
..
Lassen Sie uns dies mit einigen weiteren Modulen konkretisieren: Grundsätzlich können Sie eine Verzeichnisstruktur wie folgt haben:
setup.py
Enthält herkömmlicherweise Metadateninformationen zum Quellcode, z. B.:foo
, obwohl es beliebt ist, Bindestriche durch Unterstriche zu ersetzenpython ./setup.py test
Es ist sehr umfangreich und kann sogar c-Erweiterungen im laufenden Betrieb kompilieren, wenn ein Quellmodul auf einem Entwicklungscomputer installiert wird. Für ein tägliches Beispiel empfehle ich die setup.py des PYPA Sample Repository
Wenn Sie ein Build-Artefakt freigeben, z. B. eine Kopie des Codes, mit dem nahezu identische Computer ausgeführt werden sollen, ist eine Datei "require.txt" eine beliebte Methode, um genaue Abhängigkeitsinformationen zu erfassen, wobei "install_requires" eine gute Methode zum Erfassen von Minimum und ist maximal kompatible Versionen. Da die Zielcomputer ohnehin nahezu identisch sind, empfehle ich dringend, einen Tarball mit einem gesamten Python-Präfix zu erstellen. Dies kann schwierig und zu detailliert sein, um hier darauf einzugehen. Schauen Sie sich
pip install
die--target
Option an oder virtualenv aka venv für Leads.zurück zum Beispiel
So importieren Sie eine Datei in einem Verzeichnis:
Wenn wir von foo / spam / eggs.py Code von foo / baz wollten, könnten wir ihn anhand seines absoluten Namespace anfordern:
Wenn wir die Fähigkeit reservieren wollten, eier.py in Zukunft mit einer anderen relativen
baz
Implementierung in ein anderes Verzeichnis zu verschieben , könnten wir einen relativen Import verwenden wie:quelle
Python ist ein modulares System
Python ist nicht auf ein Dateisystem angewiesen
Um Python-Code zuverlässig zu laden, müssen Sie diesen Code in einem Modul und dieses Modul in der Python-Bibliothek installieren.
Installierte Module können immer aus dem Namespace der obersten Ebene mit geladen werden
import <name>
Es gibt ein großartiges Beispielprojekt, das offiziell hier verfügbar ist: https://github.com/pypa/sampleproject
Grundsätzlich können Sie eine Verzeichnisstruktur wie folgt haben:
.
Seien Sie sicher , dass Ihr zu erklären ,
setuptools.setup()
insetup.py
,offizielles Beispiel: https://github.com/pypa/sampleproject/blob/master/setup.py
In unserem Fall möchten wir wahrscheinlich exportieren
bar.py
undfoo/__init__.py
mein kurzes Beispiel:setup.py
.
Jetzt können wir unser Modul in der Python-Bibliothek installieren. Mit pip können Sie
the_foo_project
im Bearbeitungsmodus in Ihre Python-Bibliothek installieren , sodass wir in Echtzeit daran arbeiten können.
Jetzt können wir aus jedem Python-Kontext unsere gemeinsam genutzten py_modules und Pakete laden
foo_script.py
quelle
pip install --edit foo
, fast immer in einer virtuellen Umgebung. Ich schreibe fast nie ein Modul, das nicht installiert werden soll. Wenn ich etwas falsch verstehe, würde ich es gerne wissen.editable
Ei-Links und installierte Python-Module nicht in jeder Hinsicht exakt gleich sind. Wenn Sie beispielsweise einem bearbeitbaren Modul einen neuen Namespace hinzufügen, finden Sie ihn in Ihrer Pfadsuche. Wenn dieser jedoch nicht in Ihre Datei setup.py exportiert wird, wird er nicht gepackt / installiert! Testen Sie Ihren Anwendungsfall :)