2009-08-08 7 views
120

J'ai deux modules Python:AttributeError: objet 'module' n'a pas d'attribut

a.py

import b 

def hello(): 
    print "hello" 

print "a.py" 
print hello() 
print b.hi() 

b.py

import a 

def hi(): 
    print "hi" 

Quand je lance a.py, je reçois:

AttributeError: 'module' object has no attribute 'hi' 

s l'erreur signifie-t-elle? Comment je le répare?

+12

C'est un design horrible. Pourquoi b.py importe-t-il un quand il ne référence aucune partie d'a.py? Demandez-vous comment résoudre ce problème? http://stackoverflow.com/search?q=%5Bpython%5D+circular+dependency –

+0

Notez que vos questions sont très similaires à cette réponse. Apparemment, le code de cette réponse fonctionne, mais pas le vôtre? http://stackoverflow.com/a/7336880/565879 – Buttons840

Répondre

126

Vous avez des importations de niveau supérieur mutuel, ce qui est presque toujours une mauvaise idée.

Si vous devez vraiment avoir les importations mutuelles en Python, la façon de le faire est de les importer dans une fonction:

# In b.py: 
def cause_a_to_do_something(): 
    import a 
    a.do_something() 

Maintenant a.py peut faire en toute sécurité import b sans causer de problèmes.

(À première vue, il pourrait sembler que cause_a_to_do_something() serait extrêmement inefficace, car il fait un import chaque fois que vous l'appelez, mais en fait le travail d'importation ne reçoit que fait la première fois. La seconde fois consécutive, vous importez un module , c'est une opération rapide.)

+0

Merci! Je sais pour la première fois que l'importation dans différents endroits fait une telle différence. –

+0

Veuillez noter que ceci ajoute un surcoût lorsque la fonction est appelée, car vous placez la logique d'importation au moment de l'appel de la fonction, plutôt que le temps de chargement du programme. – Rebs

+2

Intéressant; Je me demande pourquoi l'interprète ne donne pas un message d'erreur approprié dans ce cas? –

35

Le problème est la dépendance circulaire entre les modules. a les importations b et b les importations a. Mais l'un d'entre eux doit être chargé en premier - dans ce cas python finit par initialiser le module a avant b et b.hi() n'existe pas encore lorsque vous essayez d'y accéder en a.

+0

Merci! C'est ce que j'ai deviné. Mais je ne trouve pas de documents qui le mentionnent. Si j'ai besoin de deux modules, importer des attributs les uns des autres, que dois-je faire? –

+1

@Stephen Hsu: Briser les dépendances circulaires est facile. Il a déjà été demandé plusieurs fois sur SO. http://stackoverflow.com/search?q=%5Bpython%5D+circular+dependency –

+0

@ S.Lott: Merci. Je sais juste que c'est un problème de dépendances circulaires. –

63

J'ai également vu cette erreur en nommant par inadvertance un module avec le même nom que l'un des modules Python standard. Par exemple. J'ai eu un module appelé commands qui est aussi un module de bibliothèque Python. Cela s'est avéré difficile à localiser, car il a fonctionné correctement dans mon environnement de développement local, mais a échoué avec l'erreur spécifiée lors de l'exécution sur Google App Engine.

+4

c'est la réponse qui a résolu mon problème. – Tommy

+2

J'ai utilisé 'abc.py' pour écrire un test pour démontrer le comportement d'import en python, qui me mord beaucoup ... – Bin

+0

Je m'en doutais et j'ai supprimé le module .py mais j'ai oublié de supprimer le fichier .pyc qui causait toujours le problème. Erreur. – Echelon

14

J'ai eu cette erreur en faisant référence à un ENUM qui a été importé d'une manière erronée, par exemple:

from package import MyEnumClass 
# ... 
# in some method: 
return MyEnumClass.Member 

importation correcte:

from package.MyEnumClass import MyEnumClass 

espoir qui aide quelqu'un

5

Je l'ai vécu erreur car le module n'a pas été réellement importé. Le code ressemblait à ceci:

import a.b, a.c 

# ... 

something(a.b) 
something(a.c) 
something(a.d) # My addition, which failed. 

La dernière ligne a donné lieu à un AttributeError. La cause était que je n'avais pas remarqué que les sous-modules de a (a.b et a.c) étaient explicitement importés, et supposé que l'instruction import réellement importé a.

Questions connexes