Пакеты (Pakages) в Phyton

Итак, пакет — это каталог с файлами модулей. Модули объеденяются в группы по смыслу и могут использоваться в разных проектах как единый пакет (pakage). Пакет именуется в формате "snake_case" и содержит специальный модуль с именем "__init__.py". Именно наличие этого специального файла подсказывает интерпретатору Python, что каталог следует воспринимать именно как пакет.

Простейший пакет

Давайте рассмотрим пример простейшего пакета. Пусть пакет состоит из каталога package и модуля __init__.py внутри этого каталога:

package/
└── __init__.py

Файл __init__.py пусть содержит код:

# file __init__.py
NAME = 'super_package'

Это, хотя и небольшой, но уже полноценный пакет. Его можно импортировать так же, как мы импортировали бы модуль:

import package

print(package.NAME)

Заметьте — мы не импортировали файл __init__.py непосредственно. При первом обращении к пакету Python автоматически импортирует модуль __init__.py в этом пакете. Поэтому, очевидно, нельзя импортировать "просто каталог" — ведь каталог без файла __init__.py не будет полноценным пакетом!

Содержимое пакета

С простым пакетом всё ясно — его можно использовать как модуль. Но давайте уже перейдём к группировке в пакете нескольких модулей! Для этого в пакет положим ещё два модуля:

package/
├── constants.py
├── functions.py
└── __init__.py

Содержимое модуля constants.py:

# file constants.py
PERSON = 'Alice'

Содержимое модуля functions.py:

# file functions.py
def greet(who):
    print('Hello, ' + who + '!')

Когда пакет содержит другие модули, кроме __init__.py, таковые можно импортировать по их именам. В главе про модули упоминались два варианта импортирования: квалифицированный импорт и импортирование отдельных определений. Квалифицированный импорт в данном случае будет выглядеть так:

import package.functions
import package.constants

package.functions.greet(package.constants.PERSON)  # => Hello, Alice!

Этот вариант самый понятный: в строчке вызова функции greet сразу видно, откуда пришла функция, а откуда — её аргумент. Но писать имя пакета и имя модуля каждый раз — утомительно! Давайте импортируем саму функцию и аргумент:

from package.functions import greet
from package.constants import PERSON

greet(PERSON)  # => Hello, Alice!

Такая строчка вызова функции является более читаемой. Но чтобы узнать, откуда функция и константа появились потребуется посмотреть в блок импортов

Пакеты и импорты

Импорты в Python бывают двух видов: абсолютные и относительные. Понимание разницы становится особенно важным, когда вы начинаете работать с пакетами.

Абсолютные импорты

Абсолютный импорт выглядит, как указание полного пути до модуля, включающем все пакеты и подпакеты (subpackages) — да, любой пакет может содержать не только модули, но и вложенные пакеты! Полные пути гарантируют однозначность: интерпретатору всегда понятно, что и откуда импортируется, и читать такие импорты проще.

Относительные импорты

Относительные импорты выглядят так:

from . import module
from .module import function
from .subpackage.module import CONSTANT

Здесь точка означает текущую директорию для модуля, который и осуществляет импорт. К примеру, импорт из .module означают импорт из модуля, находящегося в той же директории, которая содержит модуль с данным импортом. Такая запись сложна, поэтому уже сейчас относительные импорты лишены части возможностей, которые были доступны в более ранних версиях языка.

Предпочтительным в программирование является использование абсолютных импортов.При этом приходится писать чуть больше, но читаемость кода — слишком полезное свойство, чтобы от него отказываться!