2009-08-08 37 views
120

Ho due moduli pitone:AttributeError: 'modulo' oggetto ha alcun attributo

a.py

import b 

def hello(): 
    print "hello" 

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

b.py

import a 

def hi(): 
    print "hi" 

Quando corro a.py, ottengo:

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

Che cosa fare s l'errore significa? Come lo aggiusto?

+12

Questo è un design terribile. Perché b.py importa un quando non fa riferimento a nessuna parte di a.py? Stai chiedendo come risolvere questo problema? http://stackoverflow.com/search?q=%5Bpython%5D+circular+dependency –

+0

Nota che le tue domande sono molto simili a questa risposta. Apparentemente il codice in questa risposta funziona solo per trovare, ma il tuo no? http://stackoverflow.com/a/7336880/565879 – Buttons840

risposta

126

Si hanno reciproche importazioni di livello superiore, che è quasi sempre una cattiva idea.

Se davvero necessario avere le importazioni reciproche in Python, il modo per farlo è quello di importarli all'interno di una funzione:

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

Ora a.py può tranquillamente fare import b senza causare problemi.

(A prima vista potrebbe sembrare che cause_a_to_do_something() sarebbe estremamente inefficiente perché fa un import ogni volta che si voglia chiamare, ma in realtà il lavoro solo importazione viene fatto la prima volta. La seconda e le successive volte si importa un modulo , è un'operazione rapida.)

+0

Grazie! So per la prima volta che importare in luoghi diversi fa la differenza. –

+0

Si prega di essere consapevoli che questo aggiunge overhead quando viene chiamata la funzione, come si mette la logica di importazione al momento della chiamata della funzione, piuttosto che il tempo di caricamento del programma. – Rebs

+2

Interessante; Mi chiedo perché l'interprete non dia un messaggio di errore corretto in questo caso? –

35

Il problema è la dipendenza circolare tra i moduli. a importazioni b e b importazioni a. Ma uno di questi deve essere caricato prima - in questo caso python termina il modulo di inizializzazione a prima del b e b.hi() non esiste ancora quando si tenta di accedervi in ​​a.

+0

Grazie! È quello che ho indovinato. Ma non riesco a trovare alcuni documenti menzionarlo. Se ho bisogno di due moduli per importare alcuni attributi l'uno dall'altro, cosa dovrei fare? –

+1

@Stephen Hsu: rompere le dipendenze circolari è facile. È già stato chiesto su SO molte volte. http://stackoverflow.com/search?q=%5Bpython%5D+circular+dependency –

+0

@ S.Lott: Grazie. So solo che si tratta di un problema di dipendenze circolari. –

63

Ho anche visto questo errore quando si nominava inavvertitamente un modulo con lo stesso nome di uno dei moduli Python standard. Per esempio. Avevo un modulo chiamato commands che è anche un modulo di libreria Python. Ciò si è dimostrato difficile da rintracciare poiché ha funzionato correttamente sul mio ambiente di sviluppo locale, ma non è riuscito con l'errore specificato durante l'esecuzione su Google App Engine.

+4

questa è la risposta che ha risolto il mio problema. – Tommy

+2

Ho usato 'abc.py' per scrivere un test per dimostrare il comportamento di importazione in python, che mi morde molto ... – Bin

+0

Ho sospettato questo ed ho cancellato il modulo .py ma ho dimenticato di eliminare il .pyc che stava ancora causando il errore. – Echelon

14

ho ottenuto questo errore facendo riferimento un enum che è stato importato in un modo sbagliato, ad esempio:

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

importazione corretta:

from package.MyEnumClass import MyEnumClass 

Speranza che aiuta qualcuno

5

ho sperimentato questo errore perché il modulo non è stato effettivamente importato. Il codice si presentava così:

import a.b, a.c 

# ... 

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

L'ultima riga ha comportato un AttributeError. La causa era che non ero riuscito a notare che i sottomoduli di a (a.b e a.c) erano esplicitamente importati e supponevo che la dichiarazione import importasse effettivamente a.

Problemi correlati