2009-08-08 16 views
120

Ich habe zwei Python-Modulen:Attribute: 'Modul' Objekt hat kein 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" 

Als ich a.py laufen, erhalte ich:

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

Was doe s der Fehler bedeutet? Wie repariere ich es?

+12

Dies ist ein schreckliches Design. Warum importiert b.py a, wenn es keinen Teil von a.py referenziert? Fragen Sie, wie Sie dieses Problem beheben können? http://stackoverflow.com/search?q=%5Bpython%5D+circular+dependency –

+0

Beachten Sie, dass Ihre Fragen dieser Antwort sehr ähnlich sind. Anscheinend funktioniert der Code in dieser Antwort nur, aber deiner nicht? http://Stackoverflow.com/a/7336880/565879 – Buttons840

Antwort

126

Sie haben gemeinsame Importe auf höchster Ebene, was fast immer eine schlechte Idee ist.

Wenn Sie wirklich gegenseitige Einfuhren in Python, die Art und Weise haben muss, es zu tun ist, sie innerhalb einer Funktion zu importieren:

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

jetzt sicher a.py import b Probleme, ohne dass es zu tun.

(Auf den ersten Blick erscheint es vielleicht, dass cause_a_to_do_something() wäre äußerst ineffizient sein, weil es ein import tut jedes Mal, wenn Sie es nennen, aber in Wirklichkeit wird der Import der Arbeit nur das erste Mal durchgeführt. Die zweite und die folgenden Zeiten importieren Sie ein Modul es ist eine schnelle Operation.)

+0

Danke! Ich weiß zum ersten Mal, dass der Import an verschiedenen Orten einen Unterschied macht. –

+0

Bitte beachten Sie, dass dies zu einem Overhead führt, wenn die Funktion aufgerufen wird, da Sie die Importlogik zur Funktionsaufrufzeit und nicht zur Ladezeit des Programms setzen. – Rebs

+2

Interessant; Ich frage mich, warum der Interpreter in diesem Fall keine richtige Fehlermeldung gibt? –

35

Das Problem ist die zirkuläre Abhängigkeit zwischen den Modulen. a Importe b und b Importe a. Aber einer von ihnen muss zuerst geladen werden - in diesem Fall Python endet Initialisierung Modul a vor b und b.hi() existiert noch nicht, wenn Sie versuchen, es in a zugreifen.

+0

Vielen Dank! Es ist, was ich vermutete. Aber ich kann nicht finden, dass einige Dokumente es erwähnen. Wenn ich zwei Module benötige, um einige Attribute von einander zu importieren, was soll ich tun? –

+1

@Stephen Hsu: Breaking zirkuläre Abhängigkeiten ist einfach. Es wurde bereits mehrmals bei SO gefragt. http://stackoverflow.com/search?q=%5Bpython%5D+circular+dependency –

+0

@ S.Lott: Danke. Ich weiß nur, dass es ein zirkuläres Abhängigkeitsproblem ist. –

63

Ich habe diesen Fehler auch gesehen, wenn ich versehentlich ein Modul mit dem gleichen Namen als eines der Standardpython-Module benannte. Z.B. Ich hatte ein Modul namens commands, das auch ein Python-Bibliotheksmodul ist. Dies erwies sich als schwierig, da es in meiner lokalen Entwicklungsumgebung korrekt funktionierte, aber bei der Ausführung mit Google App Engine mit dem angegebenen Fehler fehlschlug.

+4

das ist die Antwort, die mein Problem gelöst hat. – Tommy

+2

Ich habe 'abc.py' verwendet, um einen Test zu schreiben, um das Importverhalten in Python zu demonstrieren, das mich sehr beißt ... – Bin

+0

Ich vermutete dies und löschte das .py-Modul, vergaß aber, die .pyc zu löschen, die immer noch das verursachte Error. – Echelon

14

Ich habe diesen Fehler durch eine Enumeration verweisen, die in einer falschen Weise eingeführt wurde, zum Beispiel:

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

Richtige Import:

from package.MyEnumClass import MyEnumClass 

Hoffnung, dass jemand

5

ich diese Erfahrung hilft Fehler, weil das Modul nicht importiert wurde. Der Code sah wie folgt aus:

import a.b, a.c 

# ... 

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

Die letzte Zeile führte zu einem AttributeError. Die Ursache war, dass ich nicht bemerkt hatte, dass die Submodule von a (a.b und a.c) explizit importiert wurden, und angenommen, dass die import Anweisung tatsächlich importiert a.

Verwandte Themen