Итак, пакет — это каталог с файлами модулей. Модули объеденяются в группы по смыслу и могут использоваться в разных проектах как единый пакет (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 означают импорт из модуля, находящегося в той же директории,
которая содержит модуль с данным импортом.
Такая запись сложна, поэтому уже сейчас относительные импорты лишены части возможностей,
которые были доступны в более ранних версиях языка.
Предпочтительным в программирование является использование абсолютных импортов.При этом приходится писать чуть больше, но читаемость кода — слишком полезное свойство, чтобы от него отказываться!