2017-09-14 4 views
1

J'ai ce codeImportError: ne peut pas importer le nom entre deux fichiers importer le même

mainModule

from src.comp.mypackage.wait import Wait 
from src.comp.mypackage.men import Men, MenItem 

""" Code and stuff using Men and MenItem """ 

if __name__ == '__main__': 
    MenuTestDrive.main() 

hommes

from abc import ABCMeta, abstractmethod 
from src.comp.mypackage.util import NullUtil, CompUtil 

util

from src.comp.mypackage.stack import Stack 
from src.comp.mypackage.men import Men 

""" Code and stuff using Men and MenItem """ 

et lors de l'exécution mainModule On me donné cette erreur:

Traceback (most recent call last): 
    File "/home/user/PycharmProjects/pythonProj/pythonDesignPatterns/src/comp/mypackage/mainModule.py", line 2, in <module> 
    from pythonDesignPatterns.src.comp.mypackage.men import Men, MenItem 
    File "/home/user/PycharmProjects/pythonProj/pythonDesignPatterns/src/comp/mypackage/men.py", line 2, in <module> 
    from pythonDesignPatterns.src.comp.mypackage.iterator import NullUtil, CompUtil 
    File "/home/user/PycharmProjects/pythonProj/pythonDesignPatterns/src/comp/mypackage/util.py", line 2, in <module> 
    from pythonDesignPatterns.src.comp.mypackage.men import Men 

ImportError: cannot import name 'Men' 

J'utilise PyCharm, mais l'erreur à la ligne de commande est le même.

Je pourrais fournir plus de code, mais je ne pense pas qu'il y ait quelque chose d'extraordinaire avec l'utilisation des classes et ne ferait que distraire.

Où devrais-je chercher des défaillances?

+0

Est-ce que le nom 'Man' existe vraiment dans le paquet 'men'? Pourriez-vous fournir sa définition dans votre question? – Grigoriy

Répondre

2

TL; DR: python ne permet pas les importations circulaires, de sorte que vous ne pouvez pas avoir le module men importation du module util si le module util importation du module men.

réponse plus longue:

Vous devez comprendre que Python import, class, def etc sont des déclarations réellement exécutables et tout (ou presque) se produit lors de l'exécution. Lorsqu'un module est importé pour la première fois dans un processus donné, toutes les instructions de niveau supérieur sont exécutées séquentiellement, un objet instance module est créé avec tous les noms de niveau supérieur comme attributs (notez que class, def et import tous les noms de liaison) et inséré dans le cache sys.modules afin que la prochaine importation du même module le récupère directement à partir du cache.

Dans votre cas, lors de la première importation, le module men tente d'importer le module util, qui n'est pas encore sys.modules de sorte que le temps d'exécution Python localise le fichier util.py (ou .pyc) et l'exécute. Ensuite, il atteint le from src.comp.mypackage.men import Men. À ce stade, men.py n'a pas encore été entièrement exécuté et n'a donc aucun attribut Men. La solution canonique consiste soit à extraire des dépendances circulaires dans un troisième module, soit à fusionner les deux modules en un seul, en fonction de ce qui est logique pour votre cas concret (le but étant, comme toujours, d'avoir des modules à couplage faible et haute cohésion). FWIW, les dépendances circulaires sont considérées comme mauvaises, quelle que soit la langue et même si le langage les supporte.

Parfois (le plus souvent dans des frameworks complexes imposant une structure particulière à votre code et un ordre d'import spécifique), vous pouvez vous retrouver avec des chaînes de dépendances circulaires beaucoup plus complexes (comme A.funcX dépend de By, B dépend de C qui dépend de D qui dépend de E qui dépend finalement de A.funcZ) et/ou très difficile à refactoriser proprement de manière logique.En dernier recours, vous avez toujours la possibilité de différer une déclaration d'importation dans la fonction (dans ce qui précède, il s'agit de A.funcX). C'est encore considéré comme une mauvaise pratique et devrait vraiment seulement être utilisé comme le dernier recours.

En note: de votre schéma de nommage de paquets Je peux sentir une forte influence de Java. Python n'est pas Java! Non, il n'y a rien de mal avec Java, c'est juste these are two wildly different languages, avec wildly different designs, idioms and philosopies. Essayer de forcer les idiomes et les habitudes de Java dans Python sera une expérience dans la douleur et la frustration au mieux (été ici, fait que ...), donc mon conseil ici serait: oublier la plupart de ce que vous avez appris avec Java et commencer à apprendre Python à la place (pas seulement la syntaxe - la syntaxe n'est en fait qu'une partie d'une langue et pas nécessairement la plus importante). En Python, nous privilégions l'imbrication à plat, et n'essayez pas d'avoir un module par classe, vous pouvez avoir un framework complet en un seul module, ce qui est correct s'il n'y a pas de raison pratique de le diviser en sous-modules.

+0

Il s'agissait d'un code source de modèle de conception traduit à partir de Java, mais en général, je groupais des objets semblables au modèle, fusionnait des objets quand ils n'apportaient rien (par exemple interfaces Java), etc. . Merci pour le conseil de toute façon, c'est un bon – madtyn