Ich habe eine Verzeichnisstruktur ähnlich der folgenden
meta_project
project1
__init__.py
lib
module.py
__init__.py
notebook_folder
notebook.jpynb
Bei der Arbeit in , notebook.jpynb
wenn ich versuche , einen relativen Import zu verwenden , um eine Funktion für den Zugriff auf function()
in module.py
mit:
from ..project1.lib.module import function
Ich erhalte folgende Fehlermeldung:
SystemError Traceback (most recent call last)
<ipython-input-7-6393744d93ab> in <module>()
----> 1 from ..project1.lib.module import function
SystemError: Parent module '' not loaded, cannot perform relative import
Gibt es eine Möglichkeit, dies mithilfe relativer Importe zum Laufen zu bringen?
Beachten Sie, dass der Notebook-Server auf der Ebene des meta_project
Verzeichnisses instanziiert wird , sodass er Zugriff auf die Informationen in diesen Dateien haben sollte.
Beachten Sie auch, dass zumindest wie ursprünglich beabsichtigt project1
nicht als Modul gedacht war und daher keine __init__.py
Datei enthält, sondern lediglich als Dateisystemverzeichnis gedacht war . Wenn die Lösung des Problems erfordert, dass es als Modul behandelt wird und eine __init__.py
Datei (auch eine leere) enthält, ist dies in Ordnung, reicht jedoch nicht aus, um das Problem zu lösen.
Ich teile dieses Verzeichnis zwischen Computern, und relative Importe ermöglichen es mir, überall denselben Code zu verwenden. Oft verwende ich Notebooks für das schnelle Prototyping. Daher sind Vorschläge, bei denen absolute Pfade gehackt werden, wahrscheinlich nicht hilfreich.
Bearbeiten: Dies ist anders als bei relativen Importen in Python 3 , bei denen es um relative Importe in Python 3 im Allgemeinen und insbesondere um das Ausführen eines Skripts aus einem Paketverzeichnis geht. Dies hat mit der Arbeit in einem Jupyter-Notizbuch zu tun, das versucht, eine Funktion in einem lokalen Modul in einem anderen Verzeichnis aufzurufen, das sowohl unterschiedliche allgemeine als auch bestimmte Aspekte aufweist.
__init__
Dateien in Ihrem Paketverzeichnis?lib
Verzeichnis.Antworten:
Ich hatte fast das gleiche Beispiel wie Sie in diesem Notizbuch, in dem ich die Verwendung der Funktion eines benachbarten Moduls auf trockene Weise veranschaulichen wollte.
Meine Lösung bestand darin, Python über diesen zusätzlichen Modulimportpfad zu informieren, indem ich dem Notizbuch ein Snippet wie dieses hinzufügte:
Auf diese Weise können Sie die gewünschte Funktion aus der Modulhierarchie importieren:
Beachten Sie, dass leere
__init__.py
Dateien zu den Ordnern project1 / und lib / hinzugefügt werden müssen, wenn Sie diese noch nicht haben.quelle
Kam hier auf der Suche nach Best Practices für die Abstraktion von Code in Submodule bei der Arbeit in Notebooks. Ich bin mir nicht sicher, ob es eine bewährte Methode gibt. Ich habe das vorgeschlagen.
Eine Projekthierarchie als solche:
Und von
20170609-Initial_Database_Connection.ipynb
:Dies funktioniert, da das Jupyter-Notizbuch den
cd
Befehl standardmäßig analysieren kann . Beachten Sie, dass hierfür keine Python Notebook-Magie verwendet wird. Es funktioniert einfach ohne Voranstellen%bash
.Mithilfe den man bedenkt , dass in 99 von 100 I in Docker arbeite Projekt Jupyter Docker Bilder , die folgende Modifikation ist idempotent
quelle
chdir
anstatt es dem Pfad hinzuzufügen, da ich sowohl daran interessiert bin, aus dem Haupt-Repo zu importieren als auch mit einigen Dateien dort zu kommunizieren.if os.path.isdir('../lib/'): os.chdir('../lib')
; oder, besser, verwenden Sie../lib/db/
mit Ihrempostgres.py
, um nicht versehentlich in ein höheres Verzeichnis zu wechseln, das auch ein anderes enthältlib
.cd ..
zweimal ausgeführt habe .Bisher hat die akzeptierte Antwort für mich am besten funktioniert. Ich war jedoch immer besorgt, dass es ein wahrscheinliches Szenario gibt, in dem ich das
notebooks
Verzeichnis in Unterverzeichnisse umgestalten könnte, wobei ich dasmodule_path
in jedem Notizbuch ändern muss. Ich habe beschlossen, in jedem Notebook-Verzeichnis eine Python-Datei hinzuzufügen, um die erforderlichen Module zu importieren.Somit mit folgender Projektstruktur:
Ich habe die Datei
project_path.py
in jedem Notizbuch-Unterverzeichnis (notebooks/explore
undnotebooks/explain
) hinzugefügt . Diese Datei enthält den Code für relative Importe (von @metakermit):Auf diese Weise muss ich nur relative Importe innerhalb der
project_path.py
Datei und nicht in die Notizbücher durchführen. Die Notebooks-Dateien müssten dannproject_path
vor dem Import nur noch importiert werdenlib
. Zum Beispiel in0.0-notebook.ipynb
:Die Einschränkung hier ist, dass das Umkehren der Importe nicht funktionieren würde. DAS FUNKTIONIERT NICHT:
Daher ist bei der Einfuhr Vorsicht geboten.
quelle
Ich habe gerade diese hübsche Lösung gefunden:
Sie möchten nur einige Funktionen dieser Datei
Wenn die Python-Version> = 3.3 ist, benötigen Sie keine init.py-Datei im Ordner
quelle
if ".." not in sys.path: ... sys.path.insert(0,"..")
Ich recherchiere dieses Thema selbst und habe die Antworten gelesen. Ich empfehle die Verwendung der Bibliothek path.py, da sie einen Kontextmanager zum Ändern des aktuellen Arbeitsverzeichnisses bietet.
Sie haben dann so etwas wie
Sie können die
isdir
Anweisung jedoch einfach weglassen .Hier füge ich Druckanweisungen hinzu, um zu verfolgen, was passiert
welche Ausgaben in diesem Beispiel (wo lib ist
/home/jovyan/shared/notebooks/by-team/data-vis/demos/lib
):Da die Lösung einen Kontextmanager verwendet, können Sie garantiert zu Ihrem vorherigen Arbeitsverzeichnis zurückkehren, unabhängig davon, in welchem Status sich Ihr Kernel vor der Zelle befand und welche Ausnahmen beim Importieren Ihres Bibliothekscodes ausgelöst werden.
quelle
Hier sind meine 2 Cent:
sys importieren
Ordnen Sie den Pfad zu, in dem sich die Moduldatei befindet. In meinem Fall war es der Desktop
sys.path.append ('/ Users / John / Desktop')
Importieren Sie entweder das gesamte Mapping-Modul, ABER dann müssen Sie die .notation verwenden, um die Klassen wie Mapping zuzuordnen.Shipping ()
Import Mapping # Mapping.py ist der Name meiner Moduldatei
shipit = Mapping.Shipment () #Shipment ist der Name der Klasse, die ich im Mapping-Modul verwenden muss
Oder importieren Sie die spezifische Klasse aus dem Mapping-Modul
vom Mapping Import Mapping
shipit = Shipment () # Jetzt müssen Sie die .notation nicht mehr verwenden
quelle
Ich habe festgestellt, dass Python-Dotenv hilft, dieses Problem ziemlich effektiv zu lösen. Ihre Projektstruktur ändert sich leicht, aber der Code in Ihrem Notizbuch ist für Notizbücher etwas einfacher und konsistenter.
Führen Sie für Ihr Projekt eine kleine Installation durch.
Das Projekt ändert sich dann zu:
Und schließlich ändert sich Ihr Import zu:
Ein +1 für dieses Paket ist, dass Ihre Notebooks mehrere Verzeichnisse tief sein können. python-dotenv findet das nächstgelegene in einem übergeordneten Verzeichnis und verwendet es. Ein +2 für diesen Ansatz ist, dass jupyter beim Start Umgebungsvariablen aus der ENV-Datei lädt. Double Whammy.
quelle