Übergeordnetes Verzeichnis dem PYTHONPATH hinzufügen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
theinfmonkey
User
Beiträge: 7
Registriert: Dienstag 24. August 2010, 08:59

Ich habe mein Projekt folgendermassen strukturiert:


../tools/verschiedene_module.py
../variante1/verschiedene_module.py
../variante2/verschiedene_module.py


wenn ich jetzt innerhalb der Varianten auf Module aus Tools zugreifen will muss ich den übergeordneten Pfad sys.path hinzufügen.
Das ganze sollte transportabel sein. Leider habe ich dafür noch keine schöne Lösung gefunden.

Ich machte das bisher so:

Code: Alles auswählen

import os, sys
sys.path.insert(1, os.path.join(sys.path[0], os.pardir))
und in der tat sieht der sys.path vorher und nachher verscheiden aus:

Code: Alles auswählen

[".../variante1/", ...]
...
[".../variante1/", "/variante1/..", ...]
wenn ich dann in variante1 aus tools importieren möchte

Code: Alles auswählen

import tools.modul1
funktioniert das innerhalb von Eclipse
aber nicht auf der Konsole

Code: Alles auswählen

ImportError: No module named tools.modul1
Ich versteh nicht wieso. Bin aber auch für andere Ideen zur Lösung dankbar.
Anfänger.
Benutzeravatar
/me
User
Beiträge: 3554
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

theinfmonkey hat geschrieben:

Code: Alles auswählen

import os, sys
sys.path.insert(1, os.path.join(sys.path[0], os.pardir))
Sich auf den Inhalt von sys.path[0] zu verlassen ist keine gute Idee. Ich würde mir das Elternverzeichnis der aktuellen Datei eher so holen.

Code: Alles auswählen

os.path.realpath(os.path.join(os.path.dirname(__file__), ".."))
Vielleicht kannst du aber auch einfach Intra-package references verwenden.
theinfmonkey
User
Beiträge: 7
Registriert: Dienstag 24. August 2010, 08:59

Vielleicht kannst du aber auch einfach Intra-package references verwenden.
Das scheint genau das zu sein, was ich brauche, aber

Code: Alles auswählen

from .tools.modul import *
wirft

Code: Alles auswählen

ValueError: Attempted relative import in non-package
Sich auf den Inhalt von sys.path[0] zu verlassen ist keine gute Idee.
Ist ein guter Tip, aber das scheint nicht das Problem zu sein, da der Pfad zum übergeordneten Verzeichnis ja richtig hinzugefügt wird. Python scheint das aber für die folgende import-Anweisung nicht zu interessieren.
Anfänger.
BlackJack

@theinfmonkey: Damit ein Package-Import funktioniert, müssen es natürlich auch Packages sein. Schau mal in der Dokumentation wie man aus einem Verzeichnis ein Package macht.

Wenn in `sys.path` ein Pfad zu dem Verzeichnis stehen würde, dann wäre das Modul doch gefunden worden, also scheint da schon ein Problem vorzuliegen. Bei den Kürzungen, die Du an der gezeigten Ausgabe vorgenommen hast, kann man dazu aber nicht viel sagen. Wenn da zum Beispiel ein relativer Pfad drin steht, dann muss natürlich auch das aktuelle Arbeitsverzeichnis stimmen, zu dem die Angabe ja relativ ist. Auf einen bestimmten Wert in ``sys.path[0]`` sollte man sich jedenfalls nicht verlassen.
theinfmonkey
User
Beiträge: 7
Registriert: Dienstag 24. August 2010, 08:59

@theinfmonkey: Damit ein Package-Import funktioniert, müssen es natürlich auch Packages sein. Schau mal in der Dokumentation wie man aus einem Verzeichnis ein Package macht.
Dazu muss doch nur eine __init__.py in dem Verzeichnis liegen, oder? Das ist bei mir der Fall.

Nochmal mein Verzeichnis, vielleicht ist es ja dann besser zu verstehen:

/home/mario/workspace/fwtrace/src/tools/echo.py
/home/mario/workspace/fwtrace/src/tools/__init__.py
/home/mario/workspace/fwtrace/src/main/test.py
/home/mario/workspace/fwtrace/src/main/__init__.py

Alle Dateien:

Code: Alles auswählen

#/home/mario/workspace/fwtrace/src/tools/echo.py
def areYouThere():
  return "I am here."

Code: Alles auswählen

#/home/mario/workspace/fwtrace/src/main/test.py
import sys, os
sys.path.append(sys.path[0].rsplit("/", 1)[0])
print "sys.path:", sys.path[-1]

import tools.echo as echo

print "Are you there?", echo.areYouThere()
Beide __init__.py sind vorhanden und leer.
Wenn ich test.py jetzt mit Eclipse ausführe erhalte ich

Code: Alles auswählen

sys.path /home/mario/workspace/fwtrace/src
Are you there? I am here.
Den gleichen Code auf einer Konsole:

Code: Alles auswählen

mario@mario-laptop:~/workspace/fwtrace/src/main$ python test.py 
sys.path: /home/mario/workspace/fwtrace/src
Are you there? I am here.
:D Und auf einmal funktioniert es... und mir ist immer noch nicht wirklich klar, was jetzt anders ist.

Danke erstmal für die Hilfe.
Anfänger.
theinfmonkey
User
Beiträge: 7
Registriert: Dienstag 24. August 2010, 08:59

Mein Problem war...

... dumm.

Ich habe bei meinem ursprünglichen Problem einfach eine Ebene in der Verzeichnisstruktur übersehen. :oops:

Vielen Dank für eure Hilfe, ich hab ne Menge gelernt.
Anfänger.
Antworten