Почему модули Python иногда не импортируют свои подмодули?

Я заметил что-то странное сегодня, я хотел бы объяснить. Я не был на 100% уверен, как даже сформулировать это как вопрос, поэтому о Google не может быть и речи. Модуль logging не имеет доступа к модулю logging.handlers по какой-то странной причине. Попробуйте сами, если не верите мне:

>>> import logging
>>> logging.handlers
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'handlers'
>>> import logging.handlers
>>> logging.handlers
<module 'logging.handlers' from '/usr/lib/python2.6/logging/handlers.pyc'>

Кто-нибудь может объяснить, почему это происходит?


person chriscauley    schedule 23.09.2010    source источник


Ответы (4)


В Python модули необходимо импортировать, прежде чем они станут доступными. import logging импортирует только модуль ведения журнала. Бывает так, что logging это пакет с подмодулями, но эти подмодули все равно не загружаются автоматически. Итак, вам нужно явно импортировать logging.handlers, прежде чем вы сможете получить к нему доступ.

Если вам интересно, почему иногда кажется, что вам не нужен этот дополнительный импорт: некоторые пакеты импортируют некоторые или все свои подмодули при импорте — просто выполняя этот импорт в своих __init__.py файлах. В других случаях может случиться так, что что-то еще, что вы импортируете, также импортирует logging.handlers. Неважно, какой фрагмент кода выполняет импорт; пока что-то в вашем процессе импортирует logging.handlers до того, как вы получите к нему доступ, оно будет там. А иногда модуль, который выглядит как пакет, на самом деле таковым не является, например os и os.path. os не является пакетом, он просто импортирует правильный другой модуль (для вашей платформы) и называет его path, чтобы вы могли получить к нему доступ как os.path.

person Thomas Wouters    schedule 23.09.2010

Я также новичок в python, и после большой практики теперь я могу различать пакеты (папки), модули (.py), классы, переменные... и т.д...

если вы хотите, чтобы какая-либо из ваших папок была пакетом Python - она ​​должна содержать __init__.py файл, даже пустой файл подойдет !!!

и, как сказал Томас, вы можете импортировать дополнительный модуль в __init__.py, если хотите !!! но модули/пакеты доступны только после их импорта...

если вы хотите импортировать все из модуля, который вы можете использовать

from logging import *

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

from logging import handlers
print dir(handlers)

person shahjapan    schedule 23.09.2010
comment
Пожалуйста, не используйте from module import *. Это почти всегда ошибка. - person Thomas Wouters; 23.09.2010
comment
Если вы хотите, чтобы все в пакете импортировалось автоматически, выполните этот импорт в init.py вместо установки all в init.py и где-то делать «из импорта пакета *». - person Thomas Wouters; 23.09.2010
comment
from module import * НЕ ВСЕГДА ошибка, хотя в 99,9% случаев это, по крайней мере, со встроенными модулями. Я использую несколько модулей, которые требуют импорта подстановочных знаков, потому что они определяют множество констант, которые необходимо использовать. - person Falmarri; 24.09.2010
comment
Кто-нибудь, объясните, почему "из импорта модуля *" проблематично - person Pete; 24.09.2010
comment
@Pete: потому что это загрязняет стандартное пространство имен, что приводит к двусмысленности и конфликтам. Если бы у меня были import zipper и zipper.open(), вы бы точно знали, какой оупен я коллирую. Наоборот, from zipper import *, за которым следует open(), это встроенный open или zipper.open или что-то еще. import zipper as z гораздо предпочтительнее, если вы устали печатать zipper - person msw; 24.09.2010
comment
@Pete: Это также проблема, потому что вы можете неосознанно перезаписать часть своего пространства имен. Раньше я использовал from numpy import *, потому что некоторые функции numpy не работают, если вы не импортируете все numpy (ужасный недостаток дизайна с их стороны, IMO), но numpy имеет ОГРОМНОЕ количество объектов, которые он импортирует. В итоге я перезаписал множество функций (думаю, копирование было одной из них... Я слишком устал, чтобы проверять). Теперь я импортирую numpy как np, если я собираюсь использовать numpy так часто, что не могу печатать его снова и снова. - person chriscauley; 30.09.2010
comment
@dustynachos, у какой функции numpy есть этот недостаток? - person Winston Ewert; 12.07.2013

Thomas Wouters очень хорошо ответил на этот вопрос, но, увы, я нашел этот вопрос только после того, как нашел ответ в исходной документации. . С этой целью я подумал, что добавлю к этому в надежде, что в будущем он появится ближе к вершине поисковой системы.

ВОПРОС

Почему возникает ошибка: "AttributeError: модуль "имя_модуля" не имеет атрибута "имя_подмодуля", хотя мой редактор (например, Visual Code) автоматически -дополняет название подмодуля:

 import module_name
 module_name.sub_module_name(parameter)

ОТВЕТ

Ваш редактор основывает автозаполнение на файловой структуре вашего проекта, а не на поведении Python. Подмодули не импортируются «автоматически» при импорте модуля. См. документацию по Python, чтобы узнать, как «автоматически» модули при использовании

 import module_name

Ключевым вкладом в этот ответ является добавление AttributeError при попытке импортировать «модуль» или «пакет».

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

person Underflow    schedule 06.07.2019

Недавно столкнулся с такой же странной ситуацией. Итак, держу пари, вы удалили импорт сторонних библиотек. Эта удаленная библиотека содержала from logging import handlers или from logging import * и предоставила вам handlers. А в другом скрипте у вас было что-то вроде import logging и вы только что использовали logging.handlers, и вы думали, что все работает так же, как и я.

person Alexey    schedule 19.10.2016