AttributeError: у объекта 'module' нет атрибута - PullRequest
160 голосов
/ 09 августа 2009

У меня есть два модуля Python:

a.py

import b

def hello():
  print "hello"

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

b.py

import a

def hi():
  print "hi"

Когда я запускаю a.py, я получаю:

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

Что означает ошибка? Как мне это исправить?

Ответы [ 9 ]

166 голосов
/ 09 августа 2009

У вас есть взаимный импорт верхнего уровня, что почти всегда является плохой идеей.

Если вам действительно нужен взаимный импорт в Python, способ сделать это - импортировать их в функцию:

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

Теперь a.py может безопасно выполнить import b, не вызывая проблем.

(На первый взгляд может показаться, что cause_a_to_do_something() будет крайне неэффективным, поскольку он делает import каждый раз, когда вы его вызываете, но на самом деле работа по импорту выполняется только в первый раз. Второй и последующие импортировать модуль, это быстрая операция.)

82 голосов
/ 26 июня 2010

Я также видел эту ошибку, когда случайно назвал модуль с тем же именем, что и один из стандартных модулей Python. Например. У меня был модуль под названием commands, который также является модулем библиотеки Python. Это оказалось трудно отследить, так как он работал правильно в моей локальной среде разработки, но не с указанной ошибкой при запуске в Google App Engine.

40 голосов
/ 09 августа 2009

Проблема заключается в круговой зависимости между модулями. a импорт b и b импорт a. Но один из них должен быть загружен первым - в этом случае python завершает инициализацию модуля a до b, а b.hi() еще не существует, когда вы пытаетесь получить к нему доступ в a.

18 голосов
/ 17 апреля 2015

Я получил эту ошибку, сославшись на enum, который был импортирован неправильно, например ::

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

Правильный импорт:

from package.MyEnumClass import MyEnumClass

Надеюсь, что кому-то поможет

7 голосов
/ 24 июня 2016

Я столкнулся с этой ошибкой, потому что модуль фактически не был импортирован. Код выглядел так:

import a.b, a.c

# ...

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

Последняя строка привела к AttributeError. Причина была в том, что я не заметил, что подмодули a (a.b и a.c) были явно импортированы, и предположил, что оператор import действительно импортировал a.

3 голосов
/ 21 сентября 2018

Я столкнулся с этой проблемой, когда извлек более старую версию репозитория из git. Git заменил мои .py файлы, но оставил неотслеживаемыми .pyc файлы. Поскольку файлы .py и .pyc не синхронизированы, команда import в файле .py не смогла найти соответствующий модуль в файлах .pyc.

Решение состояло в том, чтобы просто удалить .pyc файлы и позволить им автоматически восстанавливаться.

2 голосов
/ 06 июня 2018

Все вышеприведенные ответы великолепны, но я бы хотел здесь побеседовать. Если вы не обнаружили проблем, упомянутых выше, попробуйте очистить вашу рабочую среду. У меня это сработало.

0 голосов
/ 09 января 2019

Круговой импорт вызывает проблемы, но в Python есть способы его уменьшения.

Проблема в том, что при запуске python a.py он запускает a.py, но не помечает его как импортированный как модуль. Так что в свою очередь a.py -> модуль импорта b -> модуль импорта a -> модуль импорта b. Последний импортирует no-op, так как b в настоящее время импортируется, и Python защищает от этого. А пока b пустой модуль. Поэтому, когда он выполняет b.hi(), он ничего не может найти.

Обратите внимание, что b.hi(), который был выполнен, находится во время a.py -> модуль b -> модуль a, а не в a.py напрямую.

В вашем конкретном примере вы можете просто запустить python -c 'import a' на верхнем уровне, поэтому первое выполнение a.py регистрируется как импорт модуля.

0 голосов
/ 13 ноября 2018

Не уверен, как, но приведенные ниже изменения отсортировали мою проблему:

У меня было одинаковое имя файла и имя импорта, например, у меня было имя файла как emoji.py, и я пытался импортировать эмодзи. Но изменение имени файла решило проблему.

Надеюсь, это поможет

...