Module aus dem übergeordneten Ordner importieren

624

Ich verwende Python 2.5.

Dies ist mein Ordnerbaum:

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

(Ich habe auch __init__.pyin jedem Ordner, hier zur besseren Lesbarkeit weggelassen)

Wie importiere ich das nibModul aus dem lifeModul heraus? Ich hoffe, dass es möglich ist, auf sys.path zu basteln.

Hinweis: Das Hauptmodul, das ausgeführt wird, befindet sich im ptdraftOrdner.

Ram Rachum
quelle
1
Was ist Ihre PYTHONPATH-Einstellung?
S.Lott
2
Ross: Ich habe dort gesucht. Was soll ich deswegen machen? Ich habe schon eine __init__.py. S.Lott: Ich weiß nicht, wie ich das überprüfen soll ...
Ram Rachum
4
Echo $ PYTHONPATH aus der Shell; System importieren; Drucken Sie sys.path in Python aus. docs.python.org/tutorial/…
S.Lott
@FlipMcF Google ist eine sprudelnde Suchmaschine, daher spielt es keine Rolle, dass dieses Ergebnis für Sie ziemlich hoch ist. Weitaus wichtiger ist die Tatsache, dass die nicht sprudelnde Suchmaschine DuckDuckGo dies ebenfalls sehr hoch einordnet.
ArtOfWarfare
3
Ich empfehle dringend, alle sys.pathoder PYTHONPATHAntworten zu überspringen und die ausgezeichnete Antwort von np8 zu lesen . Ja, es ist eine lange Lektüre. Ja, es sieht nach viel Arbeit aus. Aber es ist die einzige Antwort, die das Problem tatsächlich richtig und sauber löst.
Aran-Fey

Antworten:

118

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

Sie müssen das Verzeichnis, das ptdraftPYTHONPATH enthält , hinzufügen

Sie sagten, das import nibhat bei Ihnen funktioniert, das bedeutet wahrscheinlich, dass Sie sich ptdraftselbst (nicht das übergeordnete Element) zu PYTHONPATH hinzugefügt haben.

hasen
quelle
15
Alles zu Pythonpath hinzufügen zu müssen, ist keine gute Lösung, wenn Sie mit vielen Paketen arbeiten, die niemals wiederverwendet werden.
Jason Cheng
@ JasonCheng: Warum sind sie dann Pakete ?
Davis Herring
7
Für mich hat diese Antwort geklappt. Um es jedoch expliziter zu machen, ist das Verfahren bis import sysund dannsys.path.append("..\<parent_folder>")
BCJuan
603

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

BEARBEITEN : Ein weiterer Punkt '.' zwei Pakete hochgehen

f3lix
quelle
177
ValueError: Attempted relative import in non-package
Endolith
18
@endolith: Sie müssen sich in einem Paket befinden, dh Sie müssen eine init .py-Datei haben.
Kirbyfan64sos
31
Versuchter relativer Import über das Toplevel-Paket hinaus
Benutzer
291
Um noch genauer zu sein, benötigen Sie eine __init__.pyDatei.
Kara Deniz
17
Siehe auch die folgende Antwort, da das Hinzufügen __init__.pynicht das einzige ist, was Sie tun müssen: stackoverflow.com/questions/11536764/…
Ben Farmer
286

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

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

Remi
quelle
97
etwas etwas kürzer:sys.path.insert(1, os.path.join(sys.path[0], '..'))
JHolta
8
Gibt es einen Grund, sys.path.append () anstelle der Einfügung zu vermeiden?
Tyler
2
@ Tyler - Es kann wichtig sein, ob irgendwo anders als das parentdir, aber in einem der bereits angegebenen Pfade sys.pathgibt es ein anderes Modul mit dem Namen 'mymodule'. Durch Einfügen von parentdirals erstes Element der sys.pathListe wird sichergestellt, dass parentdirstattdessen das Modul von importiert wird.
Remi
5
@JHolta Wenn Sie nicht mit Paketen zu tun haben, ist Ihre die beste Lösung.
Jonathon Reinhart
5
@JHolta tolle Idee. sys.path.insert(1, os.path.realpath(os.path.pardir))funktioniert auch.
SpeedCoder5
177

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

Lösung ohne sys.pathHacks

Zusammenfassung

  • Wickeln Sie den Code in einen Ordner (zB packaged_stuff)
  • Verwenden Sie das Erstellungsskript, setup.pyin 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

Installieren

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 rufe den .Stammordner auf und in meinem Fall befindet er sich in C:\tmp\test_imports.

Schritte

1) Fügen Sie a setup.pyzum Stammordner hinzu

Der Inhalt der setup.pykann einfach sein

from setuptools import setup, find_packages

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

Grundsätzlich würde "any" setup.pyfunktionieren. 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. Die Verwendung von virtuellen Umgebungen sind nicht unbedingt erforderlich, aber sie werden wirklich Sie auf lange Sicht helfen (wenn Sie mehr als 1 Projekt laufenden haben ..). Die grundlegendsten Schritte sind (im Stammordner ausführen)

  • Erstellen Sie eine virtuelle Umgebung
    • python -m venv venv
  • Aktivieren Sie die virtuelle Umgebung
    • . /venv/bin/activate(Linux) oder ./venv/Scripts/activate(Win)

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.

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 im bearbeitbaren Zustand

Installieren Sie Ihr Top-Level-Paket myprojectmit pip. Der Trick besteht darin, -ebei der Installation das Flag 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 aus

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

Sie können auch sehen, dass es mithilfe von installiert wird 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

4) Importieren Sie mainfoldervor jedem Import

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


Beispiel Verwendung

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 __name__ == '__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!
np8
quelle
1
Warum funktioniert das? Verändert es irgendwie den PYTHONPATH hinter den Kulissen?
Homero Esmeraldo
2
Warum ist dies besser oder eleganter als der sys.path-Ansatz?
Homero Esmeraldo
5
@ HomeroBarrocasSEsmeraldo Gute Fragen. PYTHONPATH env var ist unberührt. Dies wird in Site-Paketen installiert , die bereits aktiviert sind sys.pathund in denen der Code normalerweise von Endbenutzern installiert wird. Das ist besser als sys.pathHacks (und Sie können PYTHONPATH in diese Kategorie von Pfad-Hacks aufnehmen), da sich der in der Entwicklung befindliche Code für Sie genauso verhalten sollte wie für andere Benutzer. Im Gegensatz dazu werden Importanweisungen bei Verwendung von Pfadänderungen auf andere Weise aufgelöst.
wim
5
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 Ihrem Arbeitsverzeichnis angezeigt werden. Für den Fall, dass Sie diesen Eintrag löschen müssen, löschen Sie die Eidatei manuell und entfernen Sie den Eintrag aus der einfachen Installation in dist-Paketen (Site-Pakete, wenn Sie pip verwendet haben).
Rakshit Kothari
2
Warum sollten die Kopfschmerzen beim Python-Import noch komplizierter werden? Wir müssen eine Setup-Datei schreiben, eine virtuelle Umgebung, eine Pip-Installation? Oh mein Gott!
Emerson Xu
68

Sie können den betriebssystemabhängigen Pfad im "Modul-Suchpfad" verwenden, der in sys.path aufgeführt ist . So können Sie einfach ü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 Python 3.

Shinbero
quelle
6
Dies ist relativ zum aktuellen Verzeichnis, nicht unbedingt dasjenige, das das Hauptskript enthält.
Davis Herring
57

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 Python-Interpreter nach den zu importierenden Modulen sucht. In der Python-Dokumentation heißt es:

Wenn ein Modul mit dem Namen Spam importiert wird, sucht der Interpreter zuerst nach einem integrierten Modul mit diesem Namen. Wenn es nicht gefunden wird, sucht es in einer Liste von Verzeichnissen, die von der Variablen sys.path angegeben werden, nach einer Datei mit dem Namen spam.py. sys.path wird von folgenden Speicherorten 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 Standardeinstellung.

Nach der Initialisierung können Python-Programme sys.path ändern . Das Verzeichnis mit dem ausgeführten Skript befindet sich am Anfang des Suchpfads vor dem Standardbibliothekspfad. Dies bedeutet, dass Skripte in diesem Verzeichnis anstelle von gleichnamigen Modulen im 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
Ricardo Murillo
quelle
6
Ihre Antwort ist gut, funktioniert aber möglicherweise nicht immer und ist nicht sehr portabel. Wenn das Programm an einen neuen Speicherort verschoben wurde, /path/to/ptdraftmüsste es bearbeitet werden. Es gibt Lösungen, die das aktuelle Verzeichnis der Datei ermitteln und auf diese Weise auch aus dem übergeordneten Ordner importieren.
Edward
@ Edward was sind das für Techniken?
Shuklaswag
1
@Shuklaswag zum Beispiel die Antwort stackoverflow.com/questions/714063/… .
Edward
50

Sie wissen 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

Rob Ellenbroek
quelle
13
Dies funktioniert nur, wenn Ihr aktuelles Arbeitsverzeichnis so ist, dass es '..'zu dem Verzeichnis mit dem betreffenden Modul führt.
user5359531
31

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

Kürzerer Code für die Antwort - 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 die zweite Zeile durch import os.path as path, sys, inspect,
fügen Sie inspect.am Anfang von getsourcefile(Zeile 3) hinzu und entfernen Sie die erste Zeile.
- Dies importiert jedoch das gesamte Modul und benötigt möglicherweise mehr Zeit, Speicher und Ressourcen.

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 Stack Overflow-Antwort verwendet. Wie erhalte ich den Pfad der aktuell
ausgeführten Datei in Python?
um die Quelle (Dateiname) des laufenden Codes mit einem integrierten Tool zu finden.

from inspect import getsourcefile  
from os.path import abspath  

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

abspath(getsourcefile(lambda:0))

Mein Code fügt sys.pathder Python- Pfadliste einen Dateipfad hinzu ,
da Python so Module aus diesem Ordner importieren kann.

Nach dem Importieren eines Moduls in den Code empfiehlt es sich, sys.path.pop(0)in einer neuen Zeile zu arbeiten,
wenn dieser hinzugefügte Ordner ein Modul mit demselben Namen wie ein anderes Modul enthält, das
später im Programm importiert wird . Sie müssen das vor dem Import hinzugefügte Listenelement entfernen, nicht andere Pfade.
Wenn Ihr Programm keine anderen Module importiert, können Sie den Dateipfad nicht löschen, da
nach dem Beenden eines Programms (oder dem Neustart der Python-Shell) alle Änderungen an vorgenommen werdensys.path verschwinden.

Hinweise zu einer Dateinamenvariablen

In meiner Antwort wird die __file__Variable nicht verwendet , um den Dateipfad / Dateinamen des ausgeführten
Codes abzurufen, da Benutzer ihn hier häufig als unzuverlässig beschrieben haben . Sie sollten es nicht
zum Importieren von Modulen aus dem übergeordneten Ordner in Programmen verwenden, die von anderen Personen verwendet werden.

Einige Beispiele, bei denen es nicht funktioniert (Zitat aus dieser Frage zum Stapelüberlauf):

• Auf einigen Plattformen kann es nicht gefunden werden. • Manchmal ist es nicht der vollständige Dateipfad

  • py2exehat kein __file__Attribut, aber es gibt eine Problemumgehung
  • Wenn Sie von IDLE mit ausführen, execute()gibt es kein __file__Attribut
  • OS X 10.6 wo ich hinkomme NameError: global name '__file__' is not defined
Edward
quelle
1
Ich habe dies getan und den neuen Pfadeintrag mit sys.path.pop(0)sofort nach dem Import des gewünschten Moduls entfernt. Nachfolgende Importe gingen jedoch immer noch an diesen Ort. Zum Beispiel habe ich app/config, app/toolsund app/submodule/config. Von submodulefüge ich app/zum Importieren ein tools, entferne dann app/und versuche zu importieren config, aber ich bekomme app/configstattdessen app/submodule/config.
user5359531
Ich fand heraus, dass einer der toolsImporte auch configaus dem übergeordneten Verzeichnis importierte . Als ich später versuchte, sys.path.pop(0); import configdrinnen etwas zu tun submodule, erwartete app/submodule/configich es tatsächlich zu bekommen app/config. Offensichtlich gibt Python eine zwischengespeicherte Version eines Moduls mit demselben Namen zurück, anstatt tatsächlich sys.pathnach einem Modul zu suchen, das diesem Namen entspricht. sys.pathIn diesem Fall wurde es korrekt geändert. Python überprüfte es nur nicht, da das gleichnamige Modul bereits geladen wurde.
user5359531
Ich denke, dies ist der genaue Verweis auf das Problem, das ich hatte: docs.python.org/3/reference/import.html#the-module-cache
user5359531
Einige nützliche Informationen aus 5.3.1. Der Modul-Cache auf der Dokumentationsseite : Während des Imports wird der Modulname in sys.modules ... sys.modules nachgeschlagen. Durch Löschen eines Schlüssels wird der Cache-Eintrag für das genannte Modul ungültig, sodass Python beim nächsten Import erneut sucht. ... Beachten Sie jedoch, dass die beiden Objekte unterschiedlich sind, wenn Sie einen Verweis auf das Modulobjekt behalten, dessen Cache ungültig machen und dann erneut importieren. Im Gegensatz dazu importlib.reload()wird der Modulinhalt wiederverwendet und neu initialisiert ...
Edward
Noch kürzer : os.path.realpath(getsourcefile(lambda:0) + "/../.."). Wird die aktuelle Quelldatei mit zwei übergeordneten Verzeichnissymbolen angehängt. Ich habe nicht verwendet, os.path.sepda getsourcefileeine Zeichenfolge /auch unter Windows zurückgegeben wurde. realpathsorgt dafür, dass zwei Verzeichniseinträge aus dem vollständigen Pfad (in diesem Fall dem Dateinamen und dann dem aktuellen Verzeichnis) entfernt werden, der das übergeordnete Verzeichnis angibt.
Coburn
28

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

import os.path, sys
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir))
Mike
quelle
import os, sys\n sys.path.insert(0,os.path.pardir) das Gleiche, aber sorther :) (keine Zeilen in Kommentaren)
Anti Veeranna
@antiveeranna, wenn Sie verwenden, erhalten os.path.pardirSie nicht den Realpfad des Elternteils, sondern nur den relativen Pfad, von dem aus Sie densys.path.insert()
Alvas
1
Diese Antwort verwendet die __file__Variable, die unzuverlässig sein kann (nicht immer der vollständige Dateipfad, funktioniert nicht auf jedem Betriebssystem usw.), wie StackOverflow-Benutzer häufig erwähnt haben. Wenn Sie die Antwort so ändern, dass sie nicht enthalten ist, treten weniger Probleme auf und sie ist besser kompatibel. Weitere Informationen finden Sie unter stackoverflow.com/a/33532002/3787376 .
Edward
23

Ich fand die folgende Methode zum Importieren eines Pakets aus dem übergeordneten Verzeichnis des Skripts. Im Beispiel möchte ich Funktionen env.pyaus dem app.dbPaket 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)
Yu N.
quelle
Also, ein schöner sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
Einzeiler
Überhaupt sys.pathzu modifizieren ist normalerweise eine schlechte Idee. Sie müssen einen Weg ( zB , PYTHONPATH) für Ihre Bibliothek zugänglich sein , anderen Code (oder es ist sonst nicht wirklich eine Bibliothek); benutze das einfach die ganze Zeit!
Davis Herring
14

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

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

from ...module_name import *

Wenn Sie ein Modul aus dem übergeordneten Verzeichnis importieren möchten. Dann,

from ..module_name import *

Wenn Sie ein 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.

Ravin Gupta
quelle
6
Dies scheint so zu sein, wie es sein sollte, aber aus irgendeinem Grund funktioniert dies nicht auf die gleiche Weise wie die sys.path.appendobigen Hacks und ich kann meine Bibliothek nicht so importieren. Dies ist, was ich zuerst versucht habe, bevor ich anfing zu googeln :) Ok, es war dasValueError: attempted relative import beyond top-level package
juzzlin
10

Für mich ist der kürzeste und mein Lieblings-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 (Verzeichnisname) gibt den Verzeichnisnamen für das übergebene zurück.

Meiner Meinung nach sollte die Python-Projektarchitektur so ausgeführt werden, 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.

zviad
quelle
2
+1 für die Erwähnung der Möglichkeit, das Projekt umstrukturieren zu müssen (im Gegensatz zu einem Hack auf das Problem)
semore_1267
Dies bekommt nicht die Eltern, es bekommt die aktuelle
Ricky Levi
9

In einem Jupyter-Notizbuch

Solange Sie in einem Jupyter-Notizbuch arbeiten, kann diese kurze Lösung hilfreich sein:

%cd ..
import nib

Es funktioniert auch ohne __init__.py Datei.

Ich habe es mit Anaconda3 unter Linux und Windows 7 getestet.

Thomas R.
quelle
2
Wäre es nicht sinnvoll, %cd -nach dem Import hinzuzufügen , damit das aktuelle Verzeichnis des Notebooks unverändert bleibt?
Dror
8

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

Andong Zhan
quelle
8
Dies funktioniert nicht, wenn es aus einem anderen Verzeichnis ausgeführt wird.
Shatlyk Ashyralyyev
5

Wenn Sie sich nicht in einer __init__.pyPaketumgebung mit Dateien befinden, ist es mit der pathlib-Bibliothek (in> = Python 3.4 enthalten) sehr übersichtlich und intuitiv, den Pfad des übergeordneten Verzeichnisses an PYTHONPATH anzuhängen:

import sys
from pathlib import Path
sys.path.append(str(Path('.').absolute().parent))
es ist wichtig
quelle
Ist es möglich, init .py zu verwenden, um dieses Problem zu umgehen?
Künstliche
4

gleiche Art von Stil wie die vorherige Antwort - aber in weniger Zeilen: P.

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

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

YFP
quelle
Für mich ist Datei der Dateiname ohne den Pfad enthalten. Ich führe es mit "ipy filename.py" aus.
Curtis Yallop
Hallo @CurtisYallop, im obigen Beispiel fügen wir das Verzeichnis hinzu, das die Datei enthält [in der wir uns gerade befinden], in der sich die Python-Datei befindet. Der Aufruf von os.path.dirname mit dem Dateinamen sollte den Pfad der Datei und wir zurückgeben fügen DAS dem Pfad und nicht der Datei explizit hinzu - HTH's :-)
YFP
Sie gehen davon aus, dass __file__ immer den Pfad plus die Datei enthält. Manchmal enthält es nur den Dateinamen ohne den Pfad.
Curtis Yallop
@CurtisYallop - überhaupt nicht, Sir, ich gehe davon aus, dass Datei der Dateiname ist und ich verwende os.path.dirname (), um den Pfad für die Datei zu erhalten. Haben Sie ein Beispiel dafür, dass dies nicht funktioniert? Ich würde die Schritte lieben, um zu reproduzieren
YFP
1
@CurtisYallop - Nein, bin ich nicht! Ich sage das: print / _ / file / _ / gibt Ihnen den Dateinamen in Ihrem Beispiel über "file.py" - ich sage dann, dass Sie os.path.dirname () verwenden können, um den vollständigen Pfad daraus zu ziehen . Wenn Sie von einem seltsamen Ort aus anrufen und diese Beziehung möchten, können Sie Ihr Arbeitsverzeichnis leicht über das Betriebssystemmodul finden - Herrgott!
YFP
1

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

user3181121
quelle
1
Ihre Idee ist gut, aber einige Leute möchten möglicherweise ihr Modul mit ihrem Code bündeln - vielleicht, um es portabel zu machen, und müssen ihre Module nicht site-packagesjedes Mal einsetzen, wenn sie es auf einem anderen Computer ausführen.
Edward
0

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
Erel Segal-Halevi
quelle