Сообщить об ошибке.

Вложенные пакеты модулей

Пакеты могут содержать вложенные пакеты произвольной глубины. Имена вложенных пакетов отделены от имени родительского пакета точками, похожими на стандартный синтаксис доступа к атрибутам 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 каждый элемент, кроме последнего, должен быть пакетом или вложенным пакетом. Последний элемент точечной нотации может быть модулем или пакетом, но не может быть классом, функцией или переменной, определенной в предыдущем элементе.