При импорте установленного пакета из скрипта повышается "Модуль AttributeError:не имеет атрибута" или "ImportError:не может импортировать имя".

python exception python-module shadowing


У меня есть скрипт с именем requests.py который импортирует пакет запросов. Сценарий либо не может получить доступ к атрибутам из пакета, либо не может импортировать их. Почему это не работает и как мне это исправить?

Следующий код вызывает AttributeError .

import requests

res = requests.get('http://www.google.ca')
print(res)
Traceback (most recent call last):
  File "/Users/me/dev/rough/requests.py", line 1, in <module>
    import requests
  File "/Users/me/dev/rough/requests.py", line 3, in <module>
    requests.get('http://www.google.ca')
AttributeError: module 'requests' has no attribute 'get'

Следующий код вызывает ImportError .

from requests import get

res = get('http://www.google.ca')
print(res)
Traceback (most recent call last):
  File "requests.py", line 1, in <module>
    from requests import get
  File "/Users/me/dev/rough/requests.py", line 1, in <module>
    from requests import get
ImportError: cannot import name 'get'

Или код, который импортирует из модуля внутри пакета requests :

from requests.auth import AuthBase
Traceback (most recent call last):
  File "requests.py", line 1, in <module>
    from requests.auth import AuthBase
  File "/Users/me/dev/rough/requests.py", line 1, in <module>
    from requests.auth import AuthBase
ImportError: No module named 'requests.auth'; 'requests' is not a package




Answer 1 idjaw


Это происходит потому, что ваш локальный модуль с именем requests.py скрывает установленный модуль requests вы пытаетесь использовать. Текущий каталог добавляется к sys.path , поэтому локальное имя имеет приоритет над установленным именем.

Дополнительный совет по отладке,когда дело доходит до этого,это внимательно посмотреть на Traceback,и понять,что имя вашего скрипта,о котором идет речь,соответствует модулю,который вы пытаетесь импортировать:

Обратите внимание на имя,которое вы использовали в вашем сценарии:

File "/Users/me/dev/rough/requests.py", line 1, in <module>

Модуль, который вы пытаетесь импортировать: requests

Переименуйте свой модуль на что-нибудь другое,чтобы избежать столкновения названий.

Python может генерировать requests.pyc файл рядом с requests.py файл (в __pycache__ каталоге в Python 3). Удалите его также и после переименования, поскольку интерпретатор по-прежнему будет ссылаться на этот файл, повторно создавая ошибку. Однако файл pyc в __pycache__ не должен влиять на ваш код, если файл py был удален.

В примере, переименовав файл в my_requests.py , удаляя requests.pyc , и работает снова успешно печатает <Response [200]> .




Answer 2 Dave Rove


Для автора исходного вопроса и для тех, кто ищет в строке «AttributeError: модуль не имеет атрибута», общее объяснение согласно принятому ответу состоит в том, что созданный пользователем сценарий имеет конфликт имен с библиотекой. имя файла. Однако обратите внимание, что проблема может заключаться не в имени скрипта, который генерирует ошибку (как это было в предыдущем случае), ни в каком-либо из имен библиотечных модулей, явно импортированных этим скриптом. Может потребоваться небольшая детективная работа, чтобы выяснить, какой файл вызывает проблему.

В качестве примера для иллюстрации проблемы представьте, что вы создаете скрипт, который использует библиотеку «десятичная дробь» для точных вычислений с плавающей запятой с десятичными числами, и называете свой скрипт « mydecimal.py », который содержит строку « import decimal ». , Там нет проблем с этим, но вы обнаружите, что это вызывает эту ошибку:

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

Это произошло бы, если бы вы ранее написали скрипт с именем « numbers.py », потому что библиотека «decimal» вызывает стандартную библиотеку «numbers», но вместо этого находит ваш старый скрипт. Даже если вы удалили это, это может не решить проблему, потому что python мог бы преобразовать это в байт-код и сохранить его в кеше как « numbers.pyc », так что вам также придется искать это.