2009-12-16 4 views
138

Je ne peux pas pour ma vie obtenir les importations relatives de python au travail. J'ai créé un exemple simple d'où il ne fonctionne pas:Quelqu'un peut-il expliquer les importations relatives de python?

La structure du répertoire est:

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

/start.py ne contient que: import sub.relative

/sub/relative.py contient seulement from .. import parent

Tous les autres fichiers sont blanc.

Lors de l'exécution de ce qui suit sur la ligne de commande:

$ cd/
$ python start.py 

je reçois:

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 

J'utilise Python 2.6. pourquoi est-ce le cas? Comment faire fonctionner cet exemple de bac à sable?

Répondre

117

Vous importez du package "sub". start.py n'est pas lui-même dans un paquet même s'il y a un __init__.py présent.

Vous devrez commencer votre programme à partir d'un répertoire sur parent.py:

./start.py 

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

Avec start.py:

import pkg.sub.relative 

Maintenant pkg est le paquet de haut niveau et votre importation relatif devrait fonctionner.


Si vous souhaitez conserver votre disposition actuelle, vous pouvez simplement utiliser import parent. Parce que vous utilisez start.py pour lancer votre interpréteur, le répertoire start.py se trouve dans votre chemin python. parent.py vit là comme un module séparé.

Vous pouvez également supprimer en toute sécurité le niveau supérieur __init__.py, si vous n'imposez rien dans un script situé plus haut dans l'arborescence.

+2

Vous confondez les termes 'module' et 'paquet'. 'start.py' représente le module 'start', 'mod' et 'mod.sub' sont des paquets, 'mod' est un paquetage de premier niveau. –

+19

Merci, mais cela semble vraiment honnête. Pour un si beau langage, je ne peux pas croire que les concepteurs créeraient une telle restriction.N'y a-t-il pas d'autre moyen? – carl

+2

Ce n'est pas idiot du tout. Les importations relatives sont un moyen de se référer à des modules frères dans un paquet. Si vous souhaitez importer un module de niveau supérieur, utilisez les importations absolues. –

15

Si vous appelez directement relative.py et si vous voulez vraiment importer depuis un module de niveau supérieur, vous devez l'ajouter explicitement à la liste sys.path.
Voici comment cela devrait fonctionner:

# 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 

Si vous pensez que ci-dessus peut causer une sorte d'incohérence, vous pouvez utiliser ceci:

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

sys.path[0] fait référence au chemin que le point d'entrée était a couru de.

Questions connexes