Как в Python работает импорт из относительных путей?

В Python относительные импорты используются для импорта модулей внутри пакета, используя точки (`.`) для указания текущей директории или родительской.
  • . (одна точка): Относительно текущего модуля.
  • .. (две точки): Относительно родительского модуля.
  • ... (три точки) и далее: Относительно предков родительского модуля.
Например, в модуле package.module1 можно использовать from . import module2 для импорта package.module2 или from .. import module3 для импорта package.module3, если package является подпакетом другого пакета. Относительные импорты работают только в рамках пакетов. Они не работают в скриптах, запускаемых напрямую (__name__ == '__main__').

В Python импорт из относительных путей позволяет импортировать модули и пакеты, находящиеся в той же директории или в родительских/дочерних директориях, без необходимости указывать полные пути к этим модулям.

Ключевым элементом для работы с относительными импортами является использование операторов . (точка) и .. (две точки).

  • . (одна точка) указывает на текущую директорию (текущий пакет). Например, если вы находитесь в модуле package.module_a, то from . import module_b импортирует модуль module_b, находящийся в той же директории, что и module_a, то есть в package.
  • .. (две точки) указывают на родительскую директорию. Например, from .. import module_c из модуля package.subpackage.module_d импортирует module_c, находящийся в директории, родительской для subpackage, то есть в package. Можно использовать больше точек для перехода по иерархии выше: ... указывает на директорию, родительскую для родительской, и так далее.

Важно:

  • Относительные импорты работают только внутри пакетов. Пакет - это директория, содержащая файл __init__.py (который может быть пустым, но должен существовать).
  • Относительные импорты не работают в скриптах, которые запускаются напрямую (как main скрипты). Если вы хотите запустить модуль как main скрипт и использовать относительные импорты, вам нужно будет изменить структуру вашего проекта и запускать его как модуль, используя python -m package.module_name.
  • Относительные импорты обычно предпочтительнее абсолютных импортов внутри пакетов, так как они делают код более переносимым и устойчивым к изменениям в структуре проекта. Однако, если модуль расположен за пределами текущего пакета, следует использовать абсолютный импорт.

Пример структуры проекта:

  my_project/
  ├── package/
  │   ├── __init__.py
  │   ├── module_a.py
  │   ├── module_b.py
  │   └── subpackage/
  │       ├── __init__.py
  │       └── module_c.py
  └── main.py
  

Пример использования относительных импортов:

В package/module_a.py:


 from . import module_b  # Импортирует package.module_b
 from .subpackage import module_c # Импортирует package.subpackage.module_c

 def my_function():
  module_b.another_function()
  module_c.yet_another_function()
  

В package/subpackage/module_c.py:


 from .. import module_b  # Импортирует package.module_b

 def yet_another_function():
  module_b.another_function()
  

Почему это важно?

Понимание относительных импортов позволяет создавать хорошо структурированные, модульные и переносимые Python-проекты.

0