2009-12-16 7 views
138

Ich kann nicht für das Leben von mir Pythons relativen Einfuhren zu arbeiten. Ich habe ein einfaches Beispiel geschaffen, in dem es nicht funktioniert:Kann jemand Pythons relative Importe erklären?

Die Verzeichnisstruktur ist:

/__init__.py 
/start.py 
/parent.py 
/sub/__init__.py 
/sub/relative.py 

/start.py enthält nur: import sub.relative

/sub/relative.py enthält nur from .. import parent

Alle anderen Dateien sind leer.

Bei der Ausführung der folgenden in der Befehlszeile:

$ cd/
$ python start.py 

ich:

Traceback (most recent call last): 
    File "start.py", line 1, in <module> 
    import sub.relative 
    File "/home/cvondrick/sandbox/sub/relative.py", line 1, in <module> 
    from .. import parent 
ValueError: Attempted relative import beyond toplevel package 

Ich bin mit Python 2.6. Warum ist das der Fall? Wie kann ich dieses Sandbox-Beispiel verwenden?

Antwort

117

Sie importieren aus dem Paket "sub". start.py ist nicht selbst in einem Paket, auch wenn es eine __init__.py vorhanden ist.

Sie benötigen würden Ihr Programm aus einem Verzeichnis über parent.py zu starten:

./start.py 

./pkg/__init__.py 
./pkg/parent.py 
./pkg/sub/__init__.py 
./pkg/sub/relative.py 

Mit start.py:

import pkg.sub.relative 

Jetzt PKG ist das Top-Level-Paket und Ihr relativer Import funktionieren soll.


Wenn Sie mit Ihrem aktuellen Layout bleiben möchten, können Sie einfach import parent verwenden. Da Sie Ihren Interpreter mit start.py starten, befindet sich das Verzeichnis, in dem sich start.py befindet, in Ihrem Python-Pfad. parent.py lebt dort als separates Modul.

Sie können die oberste Ebene __init__.py auch sicher löschen, wenn Sie nichts weiter oben im Verzeichnisbaum in ein Skript importieren.

+2

Sie verwechseln die Begriffe "Modul" und "Paket". 'start.py' repräsentiert das Modul 'start', 'mod' und 'mod' sind Pakete, 'mod' ist ein Toplevel-Paket. –

+19

Danke, aber das scheint ehrlich gesagt wirklich albern. Für eine so schöne Sprache kann ich nicht glauben, dass die Designer eine solche Einschränkung schaffen würden.Gibt es keinen anderen Weg? – carl

+2

Es ist überhaupt nicht albern. Relative Importe sind ein Verweis auf Geschwistermodule innerhalb eines Pakets. Wenn Sie ein Toplevel-Modul importieren möchten, verwenden Sie absolute Importe. –

15

Wenn Sie relative.py direkt aufrufen und d. H. Wenn Sie wirklich von einem Top-Level-Modul importieren möchten, müssen Sie es explizit zur sys.path Liste hinzufügen.
Hier ist, wie es funktionieren sollte:

# Add this line to the beginning of relative.py file 
import sys 
sys.path.append('..') 

# Now you can do imports from one directory top cause it is in the sys.path 
import parent 

# And even like this: 
from parent import Parent 

Wenn Sie die oben denken, eine Art von Inkonsistenz verursachen können, können Sie diese stattdessen verwenden:

sys.path.append(sys.path[0] + "/..") 

sys.path[0] auf den Pfad verweist, der Punkt Eintrag wurde lief von.