Пакеты могут содержать вложенные пакеты произвольной глубины. Имена вложенных пакетов отделены от имени родительского пакета точками, похожими на стандартный синтаксис доступа к атрибутам Python. Таким образом, у вас может быть модуль с именем md
и пакет pkg
, который, в свою очередь, имеет подпакет pkg.sub_pkg1
и модуль внутри этого подпакета pkg.sub_pkg1.mod2
.
Для примера создадим такую иерархию каталогов и модулей:
-- pkg | |-- sub_pkg1 | |-- mod1.py | |-- mod2.py | | |-- sub_pkg2 |-- mod3.py |-- mod4.py
Модули будут содержать следующий код:
mod1.py
:
def one(): print('Модуль 1, функция one()')
mod2.py
:
def two(): print('Модуль 2, функция two()')
mod3.py
:
def three(): print('Модуль 3, функция three()')
mod4.py
:
def four(): print('Модуль 4, функция four()')
Импорт работает так же, но для отделения имени пакета от имени вложенного пакета используется дополнительная точечная нотация:
>>> import pkg.sub_pkg1.mod1 >>> pkg.sub_pkg1.mod1.one() # Модуль 1, функция one() >>> from pkg.sub_pkg1 import mod2 >>> mod2.two() # Модуль 2, функция two() >>> from pkg.sub_pkg2.mod3 import three >>> three() # Модуль 3, функция three() >>> from pkg.sub_pkg2.mod4 import four as baz >>> baz() # Модуль 4, функция four()
Модуль в одном вложенном пакете может ссылаться на объекты в любом дочернем вложенном пакете. В примере ниже, выполним функцию one()
, определенную в модуле mod1
из модуля mod3
. Для этого изменим файл модуля mod3.py
, будем использовать абсолютный импорт модуля mod1
:
pkg/sub__pkg2/mod3.py
:
def three(): print('Модуль 3, функция three()') from pkg.sub_pkg1.mod1 import one one()
Теперь в консоли Python импортируем модуль mod3
из вложенного пакета sub_pkg2
:
>>> from pkg.sub_pkg2 import mod3 # Модуль 1, функция one() >>> mod3.one() # Модуль 1, функция one()
Для импорта вложенных пакетов можно использовать относительный импорт. Одна начальная точка указывает на относительный импорт, начиная с текущего пакета. Две или более передних точек указывают на относительный импорт в родительский пакет(ы) текущего пакета, один уровень на точку после первого.
В примере ниже from ..
вычисляет родительский пакет pkg
, а from ..sub_pkg1
вычисляется как вложенный пакет sub_pkg1
родительского пакета.
pkg/sub__pkg2/mod3.py
:
def three(): print('Модуль 3, функция three()') from .. import sub_pkg1 print(sub_pkg1) from ..sub_pkg1.mod1 import one
>>> from pkg.sub_pkg2 import mod3 # <module 'pkg.sub_pkg1' (namespace)> >>> mod3.one() # Модуль 1, функция one()
Обратите внимание, что при использовании импорта из пакета конструкции вида from pkg.sub_pkg2.mod3 import three
элемент может быть либо подмодулем (или подпакетом) пакета, либо каким-либо другим именем, определенным в пакете, например функцией, классом или переменной. Оператор import
сначала проверяет, определен ли элемент в пакете, если нет, он предполагает, что это модуль, и пытается загрузить его. Если он не находит его, то возникает исключение ImportError
.
И наоборот, при использовании синтаксиса типа import pkg.sub_pkg2.mod3
каждый элемент, кроме последнего, должен быть пакетом или вложенным пакетом. Последний элемент точечной нотации может быть модулем или пакетом, но не может быть классом, функцией или переменной, определенной в предыдущем элементе.