614 votes

Comment faire des importations relatives en Python?

Imaginez cette structure de répertoire:

app/
   __init__.py
   sub1/
      __init__.py
      mod1.py
   sub2/
      __init__.py
      mod2.py

Je suis codage mod1, et j'ai besoin d'importer quelque chose d' mod2. Comment dois-je faire?

J'ai essayé d' from ..sub2 import mod2 mais je suis une "Tentative relative à l'importation de non-package".

J'ai googlé autour mais n'a trouvé qu' "sys.path de la manipulation des" hacks. N'est-il pas un moyen propre?


Edit: toutes mes __init__.py's sont actuellement vide

Edit2: je suis en train de le faire parce que sub2 contient des classes qui sont partagés entre les sous-paquetages (sub1, subX, etc.).

Edit3: Le comportement, je suis à la recherche est la même que celle décrite dans la PPE 366 (merci John B)

382voto

John B Points 1594

Tout le monde semble vouloir de vous dire ce que vous devriez faire plutôt que de simplement répondre à la question.

Le problème est que vous utilisez le module '__principaux__' en passant par le mod1.py comme un argument à l'interprète.

À partir de PEP 328:

Relative des importations de l'utilisation d'un module __nom__ attribut pour déterminer le module de la position dans la hiérarchie des paquets. Si le module est le nom ne contient pas toute l'information de l'emballage (par exemple, il est à '__principaux__') puis par rapport importations sont résolus que si le module ont été d'un haut niveau module, indépendamment de l'endroit où le module est en fait situé sur le système de fichiers.

Dans la version 2.6 de Python, ils sont en ajoutant la possibilité de référence des modules par rapport au module principal. PEP 366 décrit le changement.

161voto

Pankaj Points 1006

Voici la solution qui fonctionne pour moi:

Je ne la relative des importations de l' from ..sub2 import mod2 et puis, si je veux l'exécuter en mod1.py puis-je aller vers le répertoire parent de l' app et exécuter le module à l'aide de python-m interrupteur python -m app.sub1.mod1.

La vraie raison pour laquelle ce problème se produit avec une relative des importations, c'est que relative des importations fonctionne en prenant l' __name__ de la propriété du module. Si le module est directement exécuté, __name__ est définie à l' __main__ et qu'il ne contient aucune information sur la structure du package. Et, c'est pourquoi python se plaint de l' relative import in non-package d'erreur.

Ainsi, en utilisant le commutateur-m vous offrir le paquet d'informations de structure de python, à travers lequel il est possible de résoudre la relative des importations avec succès.

J'ai rencontré ce problème plusieurs fois tout en faisant relative des importations. Et, après la lecture de toutes les réponses précédentes, je n'étais pas encore en mesure de comprendre comment le résoudre, de façon propre, sans avoir besoin de mettre le code réutilisable dans tous les fichiers. (Bien que certains commentaires étaient vraiment utile, merci à @ncoghlan et @XiongChiamiov)

Espérons que cela aide quelqu'un qui se bat avec une relative des importations de problème, car en passant par le PEP est vraiment pas amusant.

131voto

nosklo Points 75862
main.py
setup.py
app/ ->
    __init__.py
    package_a/ ->
       __init__.py
       module_a.py
    package_b/ ->
       __init__.py
       module_b.py
  1. Vous exécutez python main.py.
  2. main.py t: import app.package_a.module_a
  3. module_a.py t import app.package_b.module_b

Sinon 2 ou 3 peut utiliser: from app.package_a import module_a

Qui va travailler aussi longtemps que vous avez app dans votre PYTHONPATH. main.py pourrait être n'importe où ensuite.

Si vous écrivez un setup.py copier (à installer), l'ensemble du package de l'application et des sous-paquets à l'objectif du système de python dossiers, et main.py de la cible du système de script de dossiers.

55voto

lesnik Points 156

« Guido vues exécution des scripts dans un package comme un anti-modèle » (rejette PEP-3122)

J’ai passé tellement de temps à essayer de trouver une solution, lecture des messages ici sur Stack Overflow et disant à moi-même « il doit y avoir un meilleur moyen ! ». On dirait qu’il n’existe pas.

24voto

iElectric Points 2625
<pre><code></code><p>J’utilise cet extrait de code pour importer des modules de chemins, l’espoir qui aide</p></pre>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X