Frage zur Importierung und Zugriff auf eine Funktion aus einer übergeordneten Datei

Hallo zusammen,
kurz folgendes:
./interface/__init__..py ./version.py
Wie importiere ich die Datei version.py in __init__.py? Wenn beide Dateien sich auf einer Ebene befinden, kann ich sie ja problemlos mit "import version" einbinden. Aber wie geht das in diesem Fall? "import ../version" gibt leider einen Fehler beim Kompilieren aus.
Wer hat da einen Tipp für mich?

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
René Linke wrote:
Hallo zusammen,
kurz folgendes:
./interface/__init__..py ./version.py
Wie importiere ich die Datei version.py in __init__.py? Wenn beide Dateien sich auf einer Ebene befinden, kann ich sie ja problemlos mit "import version" einbinden. Aber wie geht das in diesem Fall? "import ../version" gibt leider einen Fehler beim Kompilieren aus.
Wer hat da einen Tipp für mich?
Python 2.5+ Dokumentation lesen. Stichwort "relative imports".
- -aj

Am 03.04.2010 12:08, schrieb René Linke:
./interface/__init__..py ./version.py
Wie importiere ich die Datei version.py in __init__.py?
Relative Imports wurden ja schon genannt. Bis Python 2.4 geht das so:
import os import sys sys.path.insert(1, os.path.join(sys.path[0], os.pardir)) import version
Erklärung:
sys.path[0] enthält immer das Verzeichnis des aktuellen Moduls. Wir hängen hier also das übergeordnete Verzeichnis (os.pardir entspricht "..") direkt nach dem aktuellen Verzeichnis in den Suchpfad.

Ulf Rompe schrieb:
Am 03.04.2010 12:08, schrieb René Linke: sys.path[0] enthält immer das Verzeichnis des aktuellen Moduls.
Das kann ich nicht bestätigen. M.E. nach enthält sys.path[0] normalerweise einen leeren String, der als das aktuelle Verzeichnis interpretiert wird1.
Es sei denn, irgendein anderes Modul hat vorher sys.path manipuliert.
Ich denke, eine etwas robustere Version wäre etwa so:
---> aaa/version.py <--- __version__ = '1.0' ---> end <---
---> aaa/__init__.py <--- # empty ---> end <---
---> aaa/bbb/__init__.py <--- import os import sys sys.path.insert(1, os.path.join(os.path.dirname(__file__), os.pardir)) from version import __version__ ---> end <---
Auch diese Version funktioniert allerdings nicht mit Imports von Paketen, die als Zip-Archive gepackt sind:
import sys sys.path.insert(0, 'aaa.zip') from aaa import bbb
Traceback (most recent call last): File "<stdin>", line 1, in <module> File "aaa/bbb/__init__.py", line 7, in <module> ImportError: No module named version
Chris

Am 05.04.2010 15:06, schrieb Christopher Arndt:
sys.path[0] enthält immer das Verzeichnis des aktuellen Moduls.
Das kann ich nicht bestätigen. M.E. nach enthält sys.path[0] normalerweise einen leeren String, der als das aktuelle Verzeichnis interpretiert wird1.
Das wäre definitiv defekt. Tatsächlich verwende ich das beschriebene Verfahren seit Jahren in einem Projekt, das rund um die Uhr auf verschiedenen Unix- und Windows-Plattformen eingesetzt wird. Es gab noch nie Probleme mit den Imports. Das Projekt startete mit Python2.4 und ist mittlerweile bei Python2.6 angekommen.
Weiterhin habe ich gerade eine kleine Reihe von Test-Modulen aufgesetzt, die sich kreuz und quer importieren und jeweils nur eine Debug-Meldung mit sys.path[0] ausgeben. Es kam überall der korrekte Pfad heraus.
Es sei denn, irgendein anderes Modul hat vorher sys.path manipuliert.
Definitiv nicht.

Hallo,
danke mit der Funktion "sys.path[0]", das ist auch genial!

Ulf Rompe schrieb:
Am 05.04.2010 15:06, schrieb Christopher Arndt:
sys.path[0] enthält immer das Verzeichnis des aktuellen Moduls.
Das kann ich nicht bestätigen. M.E. nach enthält sys.path[0] normalerweise einen leeren String, der als das aktuelle Verzeichnis interpretiert wird1.
Das wäre definitiv defekt. Tatsächlich verwende ich das beschriebene Verfahren seit Jahren in einem Projekt, das rund um die Uhr auf verschiedenen Unix- und Windows-Plattformen eingesetzt wird. Es gab noch nie Probleme mit den Imports. Das Projekt startete mit Python2.4 und ist mittlerweile bei Python2.6 angekommen.
Weiterhin habe ich gerade eine kleine Reihe von Test-Modulen aufgesetzt, die sich kreuz und quer importieren und jeweils nur eine Debug-Meldung mit sys.path[0] ausgeben. Es kam überall der korrekte Pfad heraus.
Es sei denn, irgendein anderes Modul hat vorher sys.path manipuliert.
Definitiv nicht.
Aus der standard library reference:
"As initialized upon program startup, the first item of this list, path[0], is the directory containing the script that was used to invoke the Python interpreter. If the script directory is not available (e.g. if the interpreter is invoked interactively or if the script is read from standard input), path[0] is the empty string, which directs Python to search modules in the current directory first. Notice that the script directory is inserted before the entries inserted as a result of PYTHONPATH.
A program is free to modify this list for its own purposes."
Ich hatte also auch nicht ganz recht, aber so wie du es beschreibst ist es nicht Standard und man sollte sich nicht darauf verlassen.
Chris

Am 06.04.2010 01:48, schrieb Christopher Arndt:
Aus der standard library reference:
"As initialized upon program startup, the first item of this list, path[0], is the directory containing the script that was used to invoke the Python interpreter. If the script directory is not available (e.g. if the interpreter is invoked interactively or if the script is read from standard input), path[0] is the empty string, which directs Python to search modules in the current directory first. Notice that the script directory is inserted before the entries inserted as a result of PYTHONPATH.
A program is free to modify this list for its own purposes."
Ich hatte also auch nicht ganz recht, aber so wie du es beschreibst ist es nicht Standard und man sollte sich nicht darauf verlassen.
In allen Situationen, in denen man den Suchpfad relativ zur aktuellen Datei erweitern muss oder auch nur möchte, kann man sich auch auf ein korrekt gesetztes sys.path[0] verlassen.
Wenn man interaktiv im Interpreter arbeitet oder Scripts auf stdin an ihn übergibt, kann man ja dieses Bedürfnis auch gar nicht haben. In genau diesen Fällen versagt übrigens auch os.path.dirname(__file__) ganz kläglich, weil __file__ dann nicht definiert ist. Man könnte nun versuchen, das abzufangen und irgendetwas anderes zu machen, aber man müsste schon definieren, was denn überhaupt eine sinnvolle Aktion wäre. Möglicherweise wäre sinnvoll, dann das dem aktuellen Arbeitsverzeichnis übergeordnete Verzeichnis zu wählen. Genau das macht meine Variante zufällig, aber ob es tatsächlich eine sinnvolle Anwendung dafür gibt, ist eher fraglich.
Wie gesagt: Wenn man es braucht, funktioniert es auch. Wo es nicht funktioniert, braucht man es auch nicht.
Einziger Wermutstropfen dabei: Pylint braucht etwas Schützenhilfe, um diese Pfaderweiterung zu verfolgen.
[x] ulf

Hallo,
danke euch für die Tipps. Konnte inzwischen das Problem lösen. Arbeite mit Python 2.6.5 und Python 3.1.2.
participants (4)
-
Andreas Jung
-
Christopher Arndt
-
René Linke
-
Ulf Rompe