Разберите практический результат импорта: какое имя появится в глобальной области видимости после выполнения кода и почему обращение к sax завершится ошибкой?
import xml.sax
print(xml.__name__)
try:
print(sax.__name__)
except NameError:
print("NameError")
В глобальной области видимости появится имя xml, но не отдельное имя sax. Поэтому программа выведет xml, затем NameError. Конструкция import xml.sax импортирует подмодуль, но связывает в текущем пространстве имён верхнеуровневое имя xml.
Иерархическая система модулей и пакетов нужна для организации большого кода и предотвращения конфликтов имён. Полное имя xml.sax сохраняет информацию о принадлежности подмодуля пакету и не загрязняет текущую область видимости множеством коротких имён.
Такой подход также позволяет явно выбирать стиль использования: обращаться к объекту как xml.sax или отдельно импортировать нужное имя через from xml import sax.
Ошибка возникает, когда разработчик ожидает, что каждая часть пути импорта автоматически станет отдельной переменной. Это приводит к неверным обращениям вроде sax.parse(...) после import xml.sax.
Неправильное предположение особенно опасно в коде с несколькими пакетами, где короткое имя может быть не определено или конфликтовать с другим объектом.
При выполнении import xml.sax Python находит пакет xml, загружает подмодуль xml.sax и обеспечивает доступ к нему через атрибут sax объекта xml. В текущей области видимости при этом создаётся привязка имени xml.
Имя sax само по себе не создаётся, поэтому его чтение вызывает NameError. Вывод будет таким:
Если нужно получить отдельное имя sax, следует написать:
В этом случае имя sax будет связано непосредственно с импортированным подмодулем. Компромисс заключается в том, что такой импорт короче, но хуже показывает происхождение имени и повышает риск конфликта с другими привязками.
Важно отличать форму импорта от факта загрузки модуля: Python может сохранить загруженный модуль в sys.modules, но наличие записи там не означает автоматического появления одноимённой переменной в каждой области видимости.
В проекте используется import xml.sax, после чего разработчик пишет sax.make_parser(). Вариант с заменой на import xml.sax as sax даёт короткое имя и явно создаёт нужную привязку, но скрывает пакетный префикс.
Вариант from xml import sax также работает и выглядит компактнее, однако при наличии нескольких модулей с именем sax источник становится менее очевидным. Для небольшого локального участка разумен алиас import xml.sax as sax; в публичном или крупном модуле часто предпочтительнее сохранять квалифицированное обращение xml.sax, чтобы происхождение имени было видно.
import xml.sax атрибут sax у объекта xml?Ответ: да, после успешного импорта подмодуль обычно доступен как xml.sax. Пакет xml выступает объектом модуля, а sax — его атрибутом, соответствующим загруженному подмодулю. Это не означает появления переменной sax в текущем пространстве имён.
import xml.sax as parser?Ответ: такая форма связывает в текущей области видимости имя parser с импортированным подмодулем xml.sax. Имена xml и sax как локальные привязки этой инструкцией не требуются. Алиас полезен для сокращения длинного пути или устранения конфликта имён.
from xml import sax после import xml.sax?Ответ: в текущей области видимости появится отдельная привязка sax, указывающая на тот же объект модуля xml.sax. Повторная загрузка исходного кода модуля обычно не требуется, поскольку импорт использует кэш sys.modules. Однако локальная привязка sax и атрибут xml.sax остаются разными именами, указывающими на один объект.