AttributeError: у объекта 'module' нет атрибута

194

У меня есть два модуля 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'

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

Стивен Хсу
источник
Обратите внимание, что ваши вопросы очень похожи на этот ответ. Видимо код в этом ответе работает просто найти, а ваш нет? stackoverflow.com/a/7336880/565879
Buttons840

Ответы:

189

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

Если вам действительно нужен взаимный импорт в 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каждый раз, когда вы вызываете его, но на самом деле работа по импорту выполняется только в первый раз. Второй и последующий раз, когда вы импортируете модуль, это быстрая операция. )

RichieHindle
источник
93

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

lucrussell
источник
42

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

STH
источник
21

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

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

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

from package.MyEnumClass import MyEnumClass

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

Стоян
источник
7

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

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.

Даг Хёйдал
источник
6

Я столкнулся с той же проблемой. исправлено с помощью reload.

import the_module_name
from importlib import reload
reload(the_module_name)
Просто мы
источник
5

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

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

craq
источник
Вы можете использовать эту команду для удаления всех .pycфайлов:find . -name "*.pyc" -exec rm -f {} \;
Олли
4

в Ubuntu 18.04 ( virtualenv , python.3.6.x ) следующий фрагмент перезагрузки решил эту проблему для меня:

main.py

import my_module  # my_module.py
from importlib import reload # reload 
reload(my_module)

print(my_module)
print(my_modeule.hello())

где:

|--main.py    
|--my_module.py

для дополнительной проверки документации : здесь

Бехзад Сезари
источник
3

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

Цзянь
источник
0

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

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

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

MD5
источник
0

Круговой импорт вызывает проблемы, но в 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регистрируется как импорт модуля.

Hot.PxL
источник
0

заказ импортирующей была причина , почему у меня были проблемы:

a.py:

############
# this is a problem
# move this to below
#############
from b import NewThing

class ProblemThing(object):
    pass

class A(object):
   ###############
   # add it here
   # from b import NewThing
   ###############
   nt = NewThing()
   pass

b.py:

from a import ProblemThing

class NewThing(ProblemThing):
    pass

Просто еще один пример того, как это может выглядеть, похоже на ответ Ричи Хинди, но с классами.

jmunsch
источник
0

Я много раз сталкивался с этой проблемой, но я не пытался копать глубже. Теперь я понимаю главный вопрос.

На этот раз моей проблемой был импорт сериализаторов (django и restframework) из разных модулей, таких как следующие:

from rest_framework import serializers

from common import serializers as srlz
from prices import models as mdlpri

# the line below was the problem 'srlzprod'
from products import serializers as srlzprod

У меня была такая проблема:

from product import serializers as srlzprod
ModuleNotFoundError: No module named 'product'

То, что я хотел сделать, было следующее:

class CampaignsProductsSerializers(srlz.DynamicFieldsModelSerializer):
    bank_name = serializers.CharField(trim_whitespace=True,)
    coupon_type = serializers.SerializerMethodField()
    promotion_description = serializers.SerializerMethodField()

    # the nested relation of the line below
    product = srlzprod.ProductsSerializers(fields=['id','name',],read_only=True,)

Итак, как указано выше, как решить эту проблему (импорт верхнего уровня), я перейду к следующим изменениям:

# change
product = srlzprod.ProductsSerializers(fields=['id','name',],read_only=True,)
# by 
product = serializers.SerializerMethodField()

# and create the following method and call from there the required serializer class
def get_product(self, obj):
        from products import serializers as srlzprod
        p_fields = ['id', 'name', ]
        return srlzprod.ProductsSerializers(
            obj.product, fields=p_fields, many=False,
        ).data

Таким образом, django runserver был выполнен без проблем:

./project/settings/manage.py runserver 0:8002 --settings=settings_development_mlazo
Performing system checks...

System check identified no issues (0 silenced).
April 25, 2020 - 13:31:56
Django version 2.0.7, using settings 'settings_development_mlazo'
Starting development server at http://0:8002/
Quit the server with CONTROL-C.

Конечное состояние строк кода было следующим:

from rest_framework import serializers

from common import serializers as srlz
from prices import models as mdlpri

class CampaignsProductsSerializers(srlz.DynamicFieldsModelSerializer):
    bank_name = serializers.CharField(trim_whitespace=True,)
    coupon_type = serializers.SerializerMethodField()
    promotion_description = serializers.SerializerMethodField()
    product = serializers.SerializerMethodField()

    class Meta:
        model = mdlpri.CampaignsProducts
        fields = '__all__'

    def get_product(self, obj):
        from products import serializers as srlzprod
        p_fields = ['id', 'name', ]
        return srlzprod.ProductsSerializers(
            obj.product, fields=p_fields, many=False,
        ).data

Надеюсь, что это может быть полезно для всех остальных.

Приветствую,

Мануэль Лазо
источник
0

В моем случае работа с Python 2.7 с версией numpy 1.15.0, она работала с

pip install statsmodels=="0.10.0"
Mondaa
источник