it-swarm.com.de

Importieren von Modulen aus dem übergeordneten Ordner

Ich verwende Python 2.5.

Dies 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 das nib -Modul aus dem life -Modul? Ich hoffe, es ist möglich, ohne mit sys.path zu basteln.

Hinweis: Das ausgeführte Hauptmodul befindet sich im Ordner ptdraft.

518
Ram Rachum

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

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

Sie sagten, dass import nib mit Ihnen zusammengearbeitet hat, was wahrscheinlich bedeutet, dass Sie ptdraft selbst (nicht dessen Eltern) zu PYTHONPATH hinzugefügt haben.

102
hasen

Sie können relative Importe verwenden (Python> = 2.5):

from ... import nib

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

EDIT: ein weiterer Punkt '.' zwei Pakete hochgehen

553
f3lix

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,sys,inspect
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0,parentdir) 

import mymodule

edit: Das __file__ Attribut wird nicht immer angegeben. Anstatt os.path.abspath(__file__) zu verwenden, schlug ich jetzt vor, das Inspect-Modul zu verwenden, um den Dateinamen (und den Pfad) der aktuellen Datei abzurufen

242
Remi

Ich habe eine ähnliche Antwort auch auf die Frage bezüglich Importen von Geschwisterpaketen gepostet. Sie können es sehen hier . Das Folgende wird mit Python 3.6.5 (Anaconda, Conda 4.5.1), Windows 10-Computer getestet.

Lösung ohne sys.path-Hacks

Konfiguration

Ich gehe von der gleichen Ordnerstruktur aus wie in der Frage

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

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

Schritte

1) Fügen Sie dem Stammordner eine setup.py hinzu

Der Inhalt des setup.py kann einfach sein

from setuptools import setup, find_packages

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

Grundsätzlich würde "any" setup.py funktionieren. Dies ist nur ein minimales Arbeitsbeispiel.

2) Verwenden Sie eine virtuelle Umgebung

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

  • Virtuelle Umgebung erstellen
    • python -m venv venv
  • Virtuelle Umgebung aktivieren
    • . /venv/bin/activate (Linux) oder ./venv/Scripts/activate (Win)

Um mehr darüber zu erfahren, rufen Sie einfach "python virtual env tutorial" oder ähnliches von Google auf. Sie benötigen wahrscheinlich nie andere Befehle als das Erstellen, Aktivieren und Deaktivieren.

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

PS C:\tmp\test_imports> python -m venv venv
PS C:\tmp\test_imports> .\venv\Scripts\activate
(venv) PS C:\tmp\test_imports>

3) Pip installieren Sie Ihr Projekt in bearbeitbarem Zustand

Installieren Sie Ihr oberstes Paket myproject mit pip. Der Trick besteht darin, bei der Installation das Flag -e zu verwenden. 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 Folgendes aus

pip install -e . (Beachten Sie den Punkt, er steht für "aktuelles Verzeichnis")

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

(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

4) Importieren Sie, indem Sie an jeden Import mainfolder anhängen

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


Beispielanwendung

nib.py

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

life.py

from ptdraft.nib import function_from_nib

if __== '__main__':
    function_from_nib()

Laufen life.py

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

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

Wenn ein Modul mit dem Namen Spam importiert wird, sucht der Interpreter zuerst nach einem integrierten Modul mit diesem Namen. Wird es nicht gefunden, sucht es nach einer Datei mit dem Namen spam.py in einer Liste von Verzeichnissen, die von der Variablen sys.path angegeben werden. sys.path wird von diesen Speicherorten aus initialisiert:

  • das Verzeichnis mit dem Eingabeskript (oder das aktuelle Verzeichnis).
  • PYTHONPATH (eine Liste von Verzeichnisnamen mit derselben Syntax wie die Shell-Variable PATH).
  • der installationsabhängige Standard.

Nach der Initialisierung können Python Programme sys.path ändern. Das Verzeichnis, in dem sich das ausgeführte Skript befindet, steht am Anfang des Suchpfads vor dem Standard-Bibliothekspfad. Dies bedeutet, dass Skripte in diesem Verzeichnis anstelle von Modulen mit demselben Namen in das Bibliotheksverzeichnis geladen werden. Dies ist ein Fehler, es sei denn, der Austausch 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
51
Ricardo Murillo

Sie können den betriebssystemabhängigen Pfad in "Modulsuchpfad" verwenden, der in sys.path aufgeführt ist. So können Sie ganz einfach das übergeordnete Verzeichnis wie folgt hinzufügen

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

Wenn Sie ein übergeordnetes Verzeichnis hinzufügen möchten,

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

Ich weiß nicht viel über python 2.
In python 3 kann der übergeordnete Ordner wie folgt hinzugefügt werden:

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

... und dann kann man Module daraus importieren

37
Rob Ellenbroek

Hier ist eine einfache Antwort, damit Sie sehen können, wie es funktioniert, klein und plattformübergreifend.
Es werden nur integrierte Module verwendet (os, sys und inspect), die funktionieren sollten
auf jedem Betriebssystem (OS), da Python dafür entwickelt wurde.

Kürzere Antwortzeiten - weniger Zeilen und Variablen

from inspect import getsourcefile
import os.path as path, sys
current_dir = path.dirname(path.abspath(getsourcefile(lambda:0)))
sys.path.insert(0, current_dir[:current_dir.rfind(path.sep)])
import my_module  # Replace "my_module" here with the module name.
sys.path.pop(0)

Ersetzen Sie für weniger Zeilen als diese die zweite Zeile durch import os.path as path, sys, inspect,
Fügen Sie inspect. am Anfang von getsourcefile (Zeile 3) ein und entfernen Sie die erste Zeile.
- dies importiert jedoch das gesamte Modul, sodass möglicherweise mehr Zeit, Speicher und Ressourcen benötigt werden.

Der Code für meine Antwort ( längere Version )

from inspect import getsourcefile
import os.path
import sys

current_path = os.path.abspath(getsourcefile(lambda:0))
current_dir = os.path.dirname(current_path)
parent_dir = current_dir[:current_dir.rfind(os.path.sep)]

sys.path.insert(0, parent_dir)

import my_module  # Replace "my_module" here with the module name.

Es wird ein Beispiel aus einer Stapelüberlauf-Antwort verwendet Wie erhalte ich den Pfad des Stroms?
Datei in Python ausgeführt?
, um die Quelle (den Dateinamen) des ausgeführten Codes mit einem integrierten Tool zu ermitteln.

from inspect import getsourcefile  
from os.path import abspath  

Als nächstes verwenden Sie einfach Folgendes, wo immer Sie die Quelldatei finden möchten:

abspath(getsourcefile(lambda:0))

Mein Code fügt einen Dateipfad zu sys.path hinzu, der Python-Pfadliste
weil dies Python erlaubt, Module aus diesem Ordner zu importieren.

Nach dem Importieren eines Moduls in den Code empfiehlt es sich, sys.path.pop(0) in einer neuen Zeile auszuführen
Wenn dieser hinzugefügte Ordner ein Modul mit demselben Namen wie ein anderes Modul hat, das importiert wird
später im Programm. Sie müssen das vor dem Import hinzugefügte Listenelement entfernen, keine anderen Pfade.
Wenn Ihr Programm keine anderen Module importiert, ist es sicher, den Dateipfad nicht zu löschen, da
Nachdem ein Programm beendet wurde (oder die Python Shell neu gestartet wurde), verschwinden alle an sys.path vorgenommenen Änderungen.

Anmerkungen zu einer Dateinamenvariablen

Meine Antwort verwendet nicht die Variable __file__, um den Dateipfad/Dateinamen der Ausführung abzurufen
Code, weil Benutzer ihn hier oft als unzuverlässig beschrieben haben. Du solltest es nicht benutzen
zum Importieren von Modulen aus dem übergeordneten Ordner in Programmen, die von anderen Personen verwendet werden.

Einige Beispiele, in denen es nicht funktioniert (Zitat aus this Stack Overflow-Frage):

• es kann nicht gefunden werden auf einigen Plattformen • es manchmal ist nicht der vollständige Dateipfad

  • py2exe hat kein __file__ Attribut, aber es gibt eine Problemumgehung
  • Wenn Sie mit execute() aus dem Leerlauf starten, gibt es kein __file__ Attribut
  • OS X 10.6, wo ich NameError: global name '__file__' is not defined bekomme
29
Edward

Hier ist eine allgemeinere Lösung, die das übergeordnete Verzeichnis in sys.path enthält (funktioniert bei mir):

import os.path, sys
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir))
28
Mike

Für mich ist der kürzeste und beliebteste Oneliner für den Zugriff auf das übergeordnete Verzeichnis:

sys.path.append(os.path.dirname(os.getcwd()))

oder:

sys.path.insert(1, os.path.dirname(os.getcwd()))

os.getcwd () gibt den Namen des aktuellen Arbeitsverzeichnisses zurück, os.path.dirname (directory_name) gibt den Verzeichnisnamen für das übergebene Verzeichnis zurück.

Meiner Meinung nach sollte die Python -Projektarchitektur so erfolgen, dass kein Modul aus dem untergeordneten Verzeichnis ein Modul aus dem übergeordneten Verzeichnis verwendet. Wenn so etwas passiert, lohnt es sich, über den Projektbaum nachzudenken.

Eine andere Möglichkeit besteht darin, der Systemumgebungsvariablen PYTHONPATH ein übergeordnetes Verzeichnis hinzuzufügen.

10
zviad

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

8
Andong Zhan

Ich fand die folgende Möglichkeit zum Importieren eines Pakets aus dem übergeordneten Verzeichnis des Skripts. Im Beispiel möchte ich Funktionen in env.py aus dem app.db -Paket importieren.

.
└── my_application
    └── alembic
        └── env.py
    └── app
        ├── __init__.py
        └── db
import os
import sys
currentdir = os.path.dirname(os.path.realpath(__file__))
parentdir = os.path.dirname(currentdir)
sys.path.append(parentdir)
6
Yu N.

Wenn Sie sich nicht in einer Paketumgebung mit __init__.py -Dateien befinden, können Sie mit der Pathlib-Bibliothek (die in> = Python 3.4 enthalten ist) den Pfad des übergeordneten Verzeichnisses sehr übersichtlich und intuitiv an den PYTHONPATH anhängen:

import sys
from pathlib import Path
sys.path.append(str(Path('.').absolute().parent))
6
itmatters

Die oben genannten Lösungen sind auch in Ordnung. Eine andere Lösung für dieses Problem ist

Wenn Sie etwas aus dem obersten Verzeichnis importieren möchten. Dann,

from ...module_name import *

Auch, wenn Sie ein beliebiges Modul aus dem übergeordneten Verzeichnis importieren möchten. Dann,

from ..module_name import *

Auch, wenn Sie ein beliebiges Modul aus dem übergeordneten Verzeichnis importieren möchten. Dann,

from ...module_name.another_module import *

Auf diese Weise können Sie eine bestimmte Methode importieren, wenn Sie möchten.

5
Ravin Gupta

gleicher Stil wie die Antwort in der Vergangenheit - aber in weniger Zeilen: P

import os,sys
parentdir = os.path.dirname(__file__)
sys.path.insert(0,parentdir)

file gibt den Speicherort zurück, an dem Sie arbeiten

4
YFP

Mit Bibliotheken arbeiten. Erstellen Sie eine Bibliothek namens nib, installieren Sie sie mit setup.py, lassen Sie sie in Site-Paketen speichern, und Ihre Probleme sind gelöst. Sie müssen nicht alles, was Sie machen, in ein einziges Paket packen. Zerbrich es in Stücke.

1
user3181121

In einem Linux-System können Sie einen Softlink vom Ordner "life" zur Datei nib.py erstellen. Dann können Sie es einfach wie folgt importieren:

import nib
0