68. Пакеты модулей в Python
В предыдущем уроке мы подробно разобрались с написанием модулей в Python. Модули тоже могут группироваться при необходимости в один каталог. Такой каталог в Python называют пакетом. Он образует новое пространство имен, включающее в себя атрибуты из подкаталогов и файлов модулей, которые в нем хранятся.
Чтобы указать путь до модуля, будем использовать точечную нотацию. Предположим, модуль b.py
находится в директории dir1
рабочей папки. Далее пример использования этого модуля:
''' a.py '''
import dir1.b
dir1.b.print_x() # => 10
Код самого модуля:
''' b.py '''
x = 10
y = [1, 2]
def print_x():
print(x)
def print_y():
print(y)
При импортировании пакетов в Python ниже версии 3.3, необходимо соблюдать важное требование: каждый каталог должен содержать файл __init__.py
. Для примера выше, каталог dir1
должен задержать этот файл (для Python ниже 3.3).
Из-за импортирования пакетов у нас увеличилось количество символов, которые необходимо набирать на клавиатуре. Это неудобно, поэтому уместно немного отклонится от темы и научиться сокращать длинные пути до модуля при помощи оператора as
.
''' a.py '''
import dir1.b as b1
b1.print_x() # => 10
Как видите из примера выше, достаточно дописать оператор as
и задать удобное для вас новое имя, которое можно использовать вместо длинного пути. Или использовать оператор from
:
''' a.py '''
from dir1 import b
b.print_x() # => 10
Вернемся к теме урока.
В начале пути программиста на Python может возникнуть мысль о бесполезности пакетов и достаточности модулей. Однако, в крупных программах пакеты выполняют полезную роль: делают импортирование более информативным и исключают неоднозначность.
Необходимость использования пакетов возникнет, когда вы будете разрабатывать несколько программ на своем компьютере и, вероятно, использовать в разных проектах модули с одинаковыми именами. Пока модули с одинаковыми именами в разных каталогах, все нормально (так как Python сначала ищет в локальном каталоге, как мы выяснили в уроке «Написание модулей в Python»). Но что, если вы хотите использовать необходимый код из каждого файла модуля? Вам нужно будет установить новые пути поиска, что приведет к импортированию только первого найденного питоном модуля, а другой окажется «вне зоны видимости». В таких ситуациях спасают пакеты Python.
Относительное импортирование
Для относительного импортирования модулей (импортирование модулей из пакета, относительно последнего) можно использовать ведущую точку, которая указывает на необходимость импортирования из текущего пакета. Например:
''' b.py '''
from . import c
…
Пример выше означает, что мы импортируем модуль c.py
, расположенный в том же пакете, что и модуль b.py
. Помимо информативности, такой способ импортирования так же позволяет избавиться от неоднозначности.
С выходом Python 3.3 стали возможны четыре способа (модели) импортирования. Три модули вы уже видели (стандартное импортирование модулей, пакетов и относительное импортирование). В Python 3.3 и более поздних версиях можно охватывать сразу несколько каталогов, т.е. объединить несколько пакетов в одно пространство имен и не использовать файл __init__.py
, о котором говорилось ранее.
Не будем глубоко зарываться в эту тему, так как со временем для вас не составит труда разобраться со всеми тонкостями, когда это понадобится на практике. Если кратко, пакеты в Python необязательный, но хороший способ добавить информативности вашему коду и избежать неоднозначного импортирования в случае существования нескольких модулей с одинаковыми названиями. В следующем уроке мы поговорим о более сложных темах, например, переменной __name__
и других операциях импортирования.