2009-08-08 22 views
120

Mam dwa moduły Pythona:AttributeError: 'moduł' obiekt ma atrybut

a.py

import b 

def hello(): 
    print "hello" 

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

b.py

import a 

def hi(): 
    print "hi" 

Kiedy biegnę a.py, otrzymuję:

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

Co za łania s błąd oznacza? Jak mogę to naprawić?

+12

To jest okropny projekt. Dlaczego b.py zaimportować, gdy nie odwołuje się do żadnej części pliku a.py? Czy pytasz, jak rozwiązać ten problem? http://stackoverflow.com/search?q=%5Bpython%5D+campcular+dependency –

+0

Pamiętaj, że Twoje pytania są bardzo podobne do tej odpowiedzi. Najwyraźniej kod w tej odpowiedzi działa, ale twój nie działa? http://stackoverflow.com/a/7336880/565879 – Buttons840

Odpowiedz

126

Masz wspólny import na najwyższym poziomie, co prawie zawsze jest złym pomysłem.

Jeśli naprawdę musi mieć wzajemne import w Pythonie, sposób na to jest importować je w funkcję:

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

Teraz a.py można bezpiecznie robić import b bez powodowania problemów.

(Na pierwszy rzut oka może się wydawać, że cause_a_to_do_something() byłaby bardzo nieefektywna, ponieważ wywołuje import przy każdym wywołaniu, ale w rzeczywistości importowanie odbywa się tylko za pierwszym razem. , to jest szybka operacja.)

+0

Dziękujemy! Po raz pierwszy wiem, że importowanie w różnych miejscach robi taką różnicę. –

+0

Należy pamiętać, że dodaje to overhead, gdy funkcja jest wywoływana, ponieważ logika importu jest umieszczana w czasie wywoływania funkcji, a nie w czasie ładowania programu. – Rebs

+2

Interesujące; Zastanawiam się, dlaczego tłumacz nie podaje w tym przypadku odpowiedniego komunikatu o błędzie? –

35

Problem polega na okrągłej zależności między modułami. a import b i b import a. Ale jeden z nich musi zostać załadowany jako pierwszy - w tym przypadku pyton kończy moduł inicjujący a, zanim b i b.hi() nie istnieje jeszcze podczas próby uzyskania do niego dostępu w a.

+0

Dziękujemy! Tak właśnie się domyślałem. Ale nie mogę znaleźć niektórych dokumentów o tym wspomnieć. Jeśli muszę dwa moduły importować niektóre atrybuty od siebie, co mam zrobić? –

+1

@Stephen Hsu: Łamanie zależności kołowych jest łatwe. To już zostało zadane na SO kilka razy. http://stackoverflow.com/search?q=%5Bpython%5D+circular+dependency –

+0

@ S.Lott: Dziękuję. Po prostu wiem, że jest to problem z zależnościami cyklicznymi. –

63

Widziałem również ten błąd, gdy nieumyślnie nazywałam moduł o tej samej nazwie co jeden ze standardowych modułów Pythona. Na przykład. Miałem moduł o nazwie commands, który jest także modułem bibliotecznym Python. Okazało się to trudne do wyśledzenia, ponieważ działało poprawnie w moim lokalnym środowisku programistycznym, ale nie powiodło się z określonym błędem podczas uruchamiania w Google App Engine.

+4

to jest odpowiedź, która rozwiązała mój problem. – Tommy

+2

Użyłem 'abc.py', aby napisać test demonstrujący zachowanie importu w pythonie, które bardzo mnie gryzie ... – Bin

+0

Podejrzewałem to i usunąłem moduł .py, ale zapomniałem usunąć plik .pyc, który nadal powodował błąd. – Echelon

14

mam ten błąd poprzez odniesienie enum, który został zaimportowany w niewłaściwy sposób, np

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

Prawidłowe import:

from package.MyEnumClass import MyEnumClass 

nadzieję, że pomoże komuś

5

ja tego doświadczyłem błąd, ponieważ moduł nie został faktycznie zaimportowany. Kod wyglądał tak:

import a.b, a.c 

# ... 

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

Ostatnia linia spowodowało AttributeError. Przyczyną było to, że nie zauważyłem, że submoduły (a.b i a.c) zostały zaimportowane i przyjęto, że instrukcja import rzeczywiście zaimportowała a.

Powiązane problemy