Чому модулі Python іноді не імпортують свої підмодулі?


88

Сьогодні я помітив щось дивне, про що хотів би пояснити. Я не був на 100% впевнений, як навіть сформулювати це як запитання, тому google не може бути і мови. Модуль реєстрації не має доступу до модуля 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'>

Хтось може пояснити, чому це відбувається?

Відповіді:


119

У Python модулі потрібно імпортувати, перш ніж вони стануть доступними. import loggingімпортує лише модуль реєстрації. Так трапляється, що loggingце пакет із підмодулями, але ці підмодулі все одно не завантажуються автоматично. Отже, вам потрібно явно імпортувати, logging.handlersперш ніж мати доступ до нього.

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


4

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

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

і як сказав Томас, ви можете імпортувати додатковий модуль у, __init__.pякщо хочете !!! але модулі / пакети доступні лише після їх імпорту ...

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

from logging import *

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

from logging import handlers
print dir(handlers)


5
Будь ласка, не використовуйте from module import *. Це майже завжди помилка.
Thomas Wouters,

Якщо ви хочете, щоб усе в пакеті імпортувалося автоматично, виконуйте ці імпорти в init .py, замість того, щоб встановлювати все в init .py і робити десь із 'import import *'.
Thomas Wouters,

2
@Pete: оскільки він "забруднює" стандартний простір імен, що призводить до двозначності та конфлікту. Якби я мав, import zipperі zipper.open()ти точно знав би, до якого відкритого я телефонував. Навпаки from zipper import *, open()це вбудований open або zipper.open або щось інше. import zipper as zнабагато кращий, якщо ви втомилися друкуватиzipper
msw

3
@Pete: Це також проблема, оскільки ви можете несвідомо перезаписати частину свого простору імен. Раніше я використовував з, numpy import *оскільки деякі функції numpy не працюють, якщо ви не імпортуєте всі numpy (жахливий недолік дизайну з їх боку IMO), але numpy має ВЕЛИЧЕЗНУ кількість об'єктів, які він імпортує. У підсумку я переписав багато функцій (я вважаю, що копія була однією ... Я занадто втомився перевіряти). Зараз я імпортую numpy як np, якщо збираюся використовувати numpy настільки, що не можу терпіти його знову і знову.
chriscauley

2
@dustynachos, яка функція numpy має цей недолік?
Вінстон Еверт

2

Томас Вутерс дуже добре відповів на це запитання, але, на жаль, це питання я знайшов лише після того, як знайшов відповідь в оригінальній документації. З цією метою я думав, що додам до цього, сподіваючись, що воно з’явиться ближче до верхньої частини пошукової системи в майбутньому.

ПИТАННЯ

Чому з'являється помилка: " AttributeError: модуль" ім'я_модуля "не має атрибута" ім'я_модуля ", хоча мій редактор (наприклад, Visual Code) автоматично заповнює ім'я підмодуля:

 import module_name
 module_name.sub_module_name(parameter)

ВІДПОВІДЬ

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

 import module_name

Ключовим внеском цієї відповіді є додавання AttributeError при спробі імпортувати `` модуль '' або `` пакет ''

Сподіваюся, це комусь допомагає!


1

Нещодавно я стикався з такою ж дивною ситуацією. Отже, я впевнений, що ви видалили сторонні імпорт бібліотек. Це видалило lib, що містило from logging import handlersабо from logging import *надало вас handlers. А в іншому сценарії ви мали щось подібне import loggingі щойно його використовували, logging.handlersі ви думали, що це так, як все працює, як я.

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