Когда Python встречает оператор import, он начинает поиск указанного модуля или пакета в определенной последовательности мест, которые можно рассматривать как иерархию поиска.
Вот основные шаги и компоненты этой иерархии:
sys.modules: Это кеш уже импортированных модулей. Python сначала проверяет здесь, чтобы избежать повторного импорта одного и того же модуля. Если модуль найден в sys.modules, Python просто возвращает ссылку на существующий объект модуля, не выполняя никаких действий по его загрузке с диска.sys.path: Это список строк, указывающих каталоги для поиска модулей. Он инициализируется из нескольких мест:
PYTHONPATH.sys.path: Python последовательно перебирает каждый каталог в sys.path. Для обычных модулей (файлы .py), Python ищет файл с именем, соответствующим импортируемому модулю и расширением .py. Для пакетов (каталоги, содержащие файл __init__.py), Python ищет каталог с именем пакета.__init__.py), он выполняет файл __init__.py. Этот файл может содержать код инициализации пакета, а также определять подмодули, экспортируемые пакетом. Он также может быть пустым. Существование __init__.py говорит Python, что данный каталог следует рассматривать как пакет.__init__.py (хотя могут его иметь). Механизм поиска для namespace packages отличается от обычных пакетов.from . import submodule или from .. import parentmodule). Точка (.) обозначает текущий пакет, а две точки (..) обозначают родительский пакет. Относительные импорты разрешаются относительно текущего местоположения модуля внутри иерархии пакетов.sys.modules. Это позволяет избежать повторного поиска и загрузки модуля при последующих импортах.Пример:
Предположим, у вас есть следующая структура директорий:
my_project/
├── my_package/
│ ├── __init__.py
│ ├── module_a.py
│ └── submodule/
│ ├── __init__.py
│ └── module_b.py
└── main.py
И вы хотите импортировать module_b в main.py:
В main.py:
from my_package.submodule import module_b
Python сначала проверит sys.modules, затем sys.path. Он найдет my_package в sys.path (если my_project находится в sys.path, или если main.py запускается из my_project). Затем он загрузит и выполнит my_package/__init__.py и my_package/submodule/__init__.py, прежде чем загрузить и выполнить my_package/submodule/module_b.py.
Важно помнить:
sys.path можно модифицировать во время выполнения для добавления дополнительных путей поиска модулей.