AttributeError: об’єкт 'module' не має атрибута


193

У мене є два модулі 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

Відповіді:


188

У вас взаємний імпорт найвищого рівня, що майже завжди є поганою ідеєю.

Якщо ви дійсно повинні мати взаємний імпорт у 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кожного разу, коли ви його викликаєте, але насправді робота над імпортом виконується лише перший раз. Другий і наступний раз, коли ви імпортуєте модуль, це швидка робота. )


93

Я також бачив цю помилку, коли мимоволі називали модуль з тим же ім'ям, як один із стандартних модулів Python. Наприклад, у мене був модуль під назвою, commandsякий також є модулем бібліотеки Python. Виявити це виявилося важко, оскільки він працював правильно в моєму локальному середовищі розробки, але не вдався із вказаною помилкою під час роботи в Google App Engine.


42

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


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файли, і дозволити їх автоматично відновити.


Ви можете скористатися цією командою для видалення всіх .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, і я намагався імпортувати смайли. Але зміна назви файлу вирішила проблему.

Сподіваюся, що це допомагає


0

Круговий імпорт створює проблеми, але Python має способи пом'якшити його вбудований.

Проблема полягає в тому, що при запуску python a.pyвін запускається, a.pyале не позначає імпортований як модуль. Отже, в свою чергу a.py-> модуль імпорту b -> модуль імпорту a -> модуль імпорту b. Останній імпорт не працює, оскільки в даний час імпортується b, а Python захищає від цього. І b - поки що порожній модуль. Тож коли він виконується b.hi(), він нічого не може знайти.

Зауважте, b.hi()що виконане виконується під час a.py-> модуль b -> модуль a, а не a.pyбезпосередньо.

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


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

Ще один приклад того, як це може виглядати, схожий на відповідь RichieHindie, але з класами.


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"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.