Importieren von Modulen aus dem übergeordneten Ordner

Lesezeit: 10 Minuten

Benutzer-Avatar
Ram Rachum

Ich verwende Python 2.5.

Das ist mein Ordnerbaum:

ptdraft/
  nib.py
  simulations/
    life/
      life.py

(Ich habe auch __init__.py in jedem Ordner, hier aus Gründen der Lesbarkeit weggelassen)

Wie importiere ich die nib Modul aus dem life Modul? Ich hoffe, dass es möglich ist, ohne Basteln mit sys.path auszukommen.

Hinweis: Das Hauptmodul, das ausgeführt wird, befindet sich in der ptdraft Mappe.

  • Ross: Ich habe dort nachgesehen. Was soll ich deswegen machen? Ich habe bereits eine __init__.py. S.Lott: Ich weiß nicht, wie ich das überprüfen soll…

    – Ram Rachum

    3. April 2009 um 14:42 Uhr

  • echo $PYTHONPATH von der Shell; System importieren; print sys.path aus Python heraus. docs.python.org/tutorial/…

    – S. Lott

    3. April 2009 um 16:27 Uhr

  • Ich empfehle dringend, alles zu überspringen sys.path oder PYTHONPATH Antworten und Auschecken der ausgezeichneten Antwort von np8. Ja, es ist eine lange Lektüre. Ja, sieht nach viel Arbeit aus. Aber es ist die einzige Antwort, die das Problem tatsächlich richtig und sauber löst.

    – Aran-Fey

    30. Oktober 2018 um 22:24 Uhr

  • Was ist mit ausführbarem Pseudocode passiert? Warum ist es so mühsam, Module aus einem übergeordneten Ordner in Python zu importieren? Das ist absurd.

    – erich

    21. Februar 2019 um 5:38 Uhr

  • Warum ist das so ein Schmerz? Nachdem Sie alle Diskussionen und Antworten gelesen haben, gibt es immer noch keine vernünftige einfache Lösung.

    – Apollys unterstützt Monica

    13. Dezember 2019 um 0:21 Uhr

Benutzer-Avatar
f3lix

Sie könnten relative Importe verwenden (python >= 2.5):

from ... import nib

(Was ist neu in Python 2.5) PEP 328: Absolute und relative Importe

BEARBEITEN: einen weiteren Punkt hinzugefügt ‘.’ um zwei Pakete nach oben zu gehen

  • ValueError: Attempted relative import in non-package

    – Endolith

    17. Oktober 2013 um 1:46 Uhr

  • @endolith: Du musst in einem Paket sein, dh du musst ein haben drin.py-Datei.

    – kirbyfan64sos

    17. Oktober 2013 um 21:59 Uhr

  • Versuchter relativer Import über das Paket der obersten Ebene hinaus

    – Benutzer

    20. Juni 2014 um 15:09 Uhr

  • Siehe auch die folgende Antwort, seit dem Hinzufügen __init__.py ist nicht das Einzige, was Sie tun müssen: stackoverflow.com/questions/11536764/…

    – Ben Farmer

    28. Oktober 2015 um 7:45 Uhr


  • Sein eben Genauer gesagt brauchst du eine __init__.py Datei.

    Benutzer4734394

    18. März 2018 um 14:49 Uhr

Benutzer-Avatar
Remi

Relative Importe (wie in from .. import mymodule) funktionieren nur in einem Paket. So importieren Sie „mymodule“, das sich im übergeordneten Verzeichnis Ihres aktuellen Moduls befindet:

import os
import sys
import inspect

currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir) 

import mymodule

bearbeiten: das __file__ Attribut ist nicht immer gegeben. Anstatt zu verwenden os.path.abspath(__file__) Ich habe jetzt vorgeschlagen, das inspect-Modul zu verwenden, um den Dateinamen (und den Pfad) der aktuellen Datei abzurufen

  • etwas kürzer: sys.path.insert(1, os.path.join(sys.path[0], '..'))

    – JHolta

    22. April 2013 um 0:55 Uhr

  • Gibt es einen Grund, sys.path.append() anstelle der Einfügung zu vermeiden?

    – Tyler

    19. Mai 2013 um 15:34 Uhr

  • @Tyler – Es kann egal sein, ob das woanders ist parentdiraber in einem der bereits angegebenen Pfade in sys.path, gibt es ein weiteres Modul mit dem Namen ‘mymodule’. Einfügen der parentdir als erstes Element der sys.path Liste stellt sicher, dass das Modul aus parentdir werden stattdessen importiert.

    – Remi

    20. Mai 2013 um 18:48 Uhr


  • @JHolta Wenn Sie nicht mit Paketen zu tun haben, ist Ihre Lösung die beste.

    – Jonathon Reinhart

    9. Oktober 2013 um 0:47 Uhr

  • @JHolta tolle Idee. sys.path.insert(1, os.path.realpath(os.path.pardir)) funktioniert auch.

    – SpeedCoder5

    7. August 2018 um 18:28 Uhr

Benutzer-Avatar
np8

Eine ähnliche Antwort habe ich auch auf die Frage zum Import aus Geschwisterpaketen gepostet. Sie können es hier sehen.

Lösung ohne sys.path hackt

Zusammenfassung

  • Wickeln Sie den Code in einen Ordner (z packaged_stuff)
  • Ein … kreieren setup.py Skript, in dem Sie setuptools.setup() verwenden.
  • Pip installiert das Paket im bearbeitbaren Zustand mit pip install -e <myproject_folder>
  • Importieren mit from packaged_stuff.modulename import function_name

Konfiguration

Ich gehe von der gleichen Ordnerstruktur wie in der Frage aus

.
└── ptdraft
    ├── __init__.py
    ├── nib.py
    └── simulations
        ├── __init__.py
        └── life
            ├── __init__.py
            └── life.py

Ich nenne die . den Stammordner, und in meinem Fall befindet es sich darin C:\tmp\test_imports.

Schritte

  1. Füge hinzu ein setup.py in den Stammordner — Der Inhalt der setup.py kann einfach sein
    from setuptools import setup, find_packages

    setup(name="myproject", version='1.0', packages=find_packages())

Grundsätzlich “beliebig” setup.py würde funktionieren. Dies ist nur ein minimales Arbeitsbeispiel.

  1. Verwenden Sie eine virtuelle Umgebung

Wenn Sie mit virtuellen Umgebungen vertraut sind, aktivieren Sie eine und fahren Sie mit dem nächsten Schritt fort. Nutzung virtueller Umgebungen nicht unbedingt erforderlich, aber sie werden Ja wirklich Ihnen auf lange Sicht helfen (wenn Sie mehr als 1 Projekt am Laufen haben …). Die grundlegendsten Schritte sind (im Stammordner ausführen)

  • Virtuelle Umgebung erstellen
    • python -m venv venv
  • Virtuelle Umgebung aktivieren
    • . venv/bin/activate (Linux) bzw ./venv/Scripts/activate (Gewinnen)
  • Virtuelle Umgebung deaktivieren
    • deactivate (Linux)

Um mehr darüber zu erfahren, googeln Sie einfach “python virtualenv tutorial” oder ähnliches. Sie benötigen wahrscheinlich nie andere Befehle als das Erstellen, Aktivieren und Deaktivieren.

Nachdem Sie eine virtuelle Umgebung erstellt und aktiviert haben, sollte Ihre Konsole den Namen der virtuellen Umgebung in Klammern anzeigen

PS C:\tmp\test_imports> python -m venv venv
PS C:\tmp\test_imports> .\venv\Scripts\activate
(venv) PS C:\tmp\test_imports>
  1. pip installieren Sie Ihr Projekt im bearbeitbaren Zustand

Installieren Sie Ihr Top-Level-Paket myproject verwenden pip. Der Trick besteht darin, die zu verwenden -e Flag bei der Installation. Auf diese Weise wird es in einem bearbeitbaren Zustand installiert, und alle an den .py-Dateien vorgenommenen Änderungen werden automatisch in das installierte Paket aufgenommen.

Führen Sie im Stammverzeichnis aus

pip install -e . (beachten Sie den Punkt, er steht für “aktuelles Verzeichnis”)

Sie können auch sehen, dass es installiert ist, indem Sie verwenden pip freeze

(venv) PS C:\tmp\test_imports> pip install -e .
Obtaining file:///C:/tmp/test_imports
Installing collected packages: myproject
  Running setup.py develop for myproject
Successfully installed myproject
(venv) PS C:\tmp\test_imports> pip freeze
myproject==1.0
  1. Import durch Voranstellen mainfolder zu jedem Import

In diesem Beispiel ist die mainfolder wäre ptdraft. Dies hat den Vorteil, dass Sie nicht auf Namenskollisionen mit anderen Modulnamen (aus der Python-Standardbibliothek oder Modulen von Drittanbietern) stoßen.


Beispielnutzung

nib.py

def function_from_nib():
    print('I am the return value from function_from_nib!')

Leben.py

from ptdraft.nib import function_from_nib

if __name__ == '__main__':
    function_from_nib()

life.py ausführen

(venv) PS C:\tmp\test_imports> python .\ptdraft\simulations\life\life.py
I am the return value from function_from_nib!

  • Warum ist dies auch besser oder eleganter als die Verwendung des sys.path-Ansatzes?

    – Homero Esmeraldo

    23. Januar 2019 um 17:23 Uhr

  • @HomeroBarrocasSEsmeraldo Gute Fragen. PYTHONPATH env var bleibt unberührt. Dies wird in Site-Pakete installiert, die bereits aktiviert sind sys.path und wo der Code normalerweise von Endbenutzern installiert wird. Das ist besser als sys.path Hacks (und Sie können die Verwendung von PYTHONPATH in diese Kategorie von Pfad-Hacks aufnehmen), da dies bedeutet, dass sich der Code in der Entwicklung für Sie genauso verhalten sollte wie für andere Benutzer. Im Gegensatz dazu würden Importanweisungen bei der Verwendung von Pfadänderungen auf andere Weise aufgelöst werden.

    – Wim

    25. März 2019 um 21:21 Uhr


  • Dies ist bei weitem DIE beste Lösung, die ich gelesen habe. Dadurch wird ein Link zu Ihrem aktuellen Verzeichnis erstellt, sodass alle Aktualisierungen des Codes direkt in Ihr Arbeitsverzeichnis übernommen werden. Falls Sie diesen Eintrag löschen müssen, löschen Sie die Egg-Datei manuell und entfernen Sie den Eintrag aus easy-install in dist-packages (site-packages, wenn Sie pip verwendet haben).

    – Rakshit Kothari

    22. August 2019 um 21:46 Uhr


  • Warum die Kopfschmerzen beim Python-Import noch komplizierter machen? Wir müssen eine Setup-Datei schreiben, eine virtuelle Umgebung, eine Pip-Installation? omg!

    – Emerson Xu

    1. Mai 2020 um 9:17 Uhr

  • Ist dieser Arbeitsaufwand zum Importieren eines Moduls im Jahr 2020 auf Python 3.8 noch erforderlich? Ich kann nicht glauben, wie kompliziert das ist.

    – rocksNwaves

    5. August 2020 um 20:06 Uhr

Benutzer-Avatar
Hasen

Es scheint, dass das Problem nicht damit zusammenhängt, dass sich das Modul in einem übergeordneten Verzeichnis oder ähnlichem befindet.

Sie müssen das Verzeichnis hinzufügen, das enthält ptdraft zu PYTHONPATH

Du hast das gesagt import nib mit Ihnen gearbeitet, das bedeutet wahrscheinlich, dass Sie hinzugefügt haben ptdraft selbst (nicht sein Elternteil) zu PYTHONPATH.

Benutzer-Avatar
Shinbero

Sie können den betriebssystemabhängigen Pfad im “Modulsuchpfad” verwenden, der in aufgeführt ist sys.Pfad . So können Sie ganz einfach ein übergeordnetes Verzeichnis wie folgt hinzufügen

import sys
sys.path.insert(0,'..')

Wenn Sie ein Eltern-Eltern-Verzeichnis hinzufügen möchten,

sys.path.insert(0,'../..')

Dies funktioniert sowohl in Python 2 als auch in 3.

  • Dies ist relativ zu der aktuell Verzeichnis, nicht einmal unbedingt dasjenige, das das Hauptskript enthält.

    – Davis Hering

    27. September 2019 um 0:48 Uhr

  • Diese Methode funktioniert in PyCharm, aber nicht in VS Code.

    – Eric xu

    1. Dezember 2021 um 16:48 Uhr

  • hat bei mir super funktioniert! Danke! … aber ich brauchte Geschwisterverzeichnis, also war meine Lösung sys.path.insert(0,'../sibling_dir')

    – Gewächshaus

    8. März um 17:50 Uhr

  • @DavisHerring Um das Problem zu beheben, verwenden Sie einen absoluten Pfad.

    – Jeyekomon

    8. Juli um 11:30 Uhr

  • @Jeyekomon: Das ersetzt lediglich eine der verschiedenen Formen der Zerbrechlichkeit in diesem Ansatz durch eine andere.

    – Davis Hering

    8. Juli um 15:23 Uhr

Benutzer-Avatar
Serg Tschernata

Keine Ahnung von Python 2.
In Python 3 kann der übergeordnete Ordner wie folgt hinzugefügt werden:

import sys 
sys.path.append('..')

…und dann kann man daraus Module importieren

  • Dies ist relativ zu der aktuell Verzeichnis, nicht einmal unbedingt dasjenige, das das Hauptskript enthält.

    – Davis Hering

    27. September 2019 um 0:48 Uhr

  • Diese Methode funktioniert in PyCharm, aber nicht in VS Code.

    – Eric xu

    1. Dezember 2021 um 16:48 Uhr

  • hat bei mir super funktioniert! Danke! … aber ich brauchte Geschwisterverzeichnis, also war meine Lösung sys.path.insert(0,'../sibling_dir')

    – Gewächshaus

    8. März um 17:50 Uhr

  • @DavisHerring Um das Problem zu beheben, verwenden Sie einen absoluten Pfad.

    – Jeyekomon

    8. Juli um 11:30 Uhr

  • @Jeyekomon: Das ersetzt lediglich eine der verschiedenen Formen der Zerbrechlichkeit in diesem Ansatz durch eine andere.

    – Davis Hering

    8. Juli um 15:23 Uhr

Benutzer-Avatar
Joe Reynolds

Wenn das Hinzufügen Ihres Modulordners zum PYTHONPATH nicht funktioniert hat, können Sie die sys.Pfad Liste in Ihrem Programm, in der der Python-Interpreter nach den zu importierenden Modulen sucht, die Python-Dokumentation sagt:

Wenn ein Modul namens Spam importiert wird, sucht der Interpreter zunächst nach einem eingebauten Modul mit diesem Namen. Wenn es nicht gefunden wird, sucht es nach einer Datei mit dem Namen spam.py in einer Verzeichnisliste, die durch die Variable sys.path angegeben wird. sys.path wird von diesen Orten aus initialisiert:

  • das Verzeichnis, das das Eingabeskript enthält (oder das aktuelle Verzeichnis).
  • PYTHONPATH (eine Liste von Verzeichnisnamen mit derselben Syntax wie die Shell-Variable PATH).
  • die installationsabhängige Vorgabe.

Nach der Initialisierung können Python-Programme modifizieren sys.Pfad. Das Verzeichnis, das das ausgeführte Skript enthält, wird am Anfang des Suchpfads platziert, vor dem Standardbibliothekspfad. Dies bedeutet, dass Skripte in diesem Verzeichnis geladen werden anstelle von gleichnamigen Modulen im Bibliotheksverzeichnis. Dies ist ein Fehler, es sei denn, der Ersatz ist beabsichtigt.

Wenn Sie dies wissen, können Sie in Ihrem Programm Folgendes tun:

import sys
# Add the ptdraft folder path to the sys.path list
sys.path.append('/path/to/ptdraft/')

# Now you can import your module
from ptdraft import nib
# Or just
import ptdraft

  • Ihre Antwort ist gut, funktioniert aber möglicherweise nicht immer und ist nicht sehr portabel. Wenn das Programm an einen neuen Ort verschoben wurde, /path/to/ptdraft müsste bearbeitet werden. Es gibt Lösungen, die das aktuelle Verzeichnis der Datei ermitteln und auf diese Weise auch aus dem übergeordneten Ordner importieren.

    – Eduard

    14. November 2015 um 10:59 Uhr

  • @Edward was sind das für Techniken?

    – Shuklaswag

    16. September 2018 um 1:37 Uhr

  • @Shuklaswag zum Beispiel die Antwort stackoverflow.com/questions/714063/….

    – Eduard

    22. September 2018 um 9:38 Uhr


1144170cookie-checkImportieren von Modulen aus dem übergeordneten Ordner

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy