Во-первых, имейте в виду, что в своем точном определении модуль - это объект в памяти интерпретатора Python, который часто создается путем чтения одного или нескольких файлов с диска. Хотя мы можем неофициально называть дисковый файл, такой как a/b/c.py
, «модулем», он на самом деле не становится единым, пока не будет объединен с информацией из нескольких других источников (таких как sys.path
) для создания объекта модуля.
(Обратите внимание, например, что два модуля с разными именами могут быть загружены из одного и того же файла, в зависимости от sys.path
и других настроек. Это именно то, что происходит с python -m my.module
, за которым следует import my.module
в интерпретаторе ; будет два объекта модуля, __main__
и my.module
, оба созданы из одного и того же файла на диске, my/module.py
.)
A package - это модуль, который может иметь подмодули (включая подпакеты). Не все модули могут сделать это. В качестве примера создайте небольшую иерархию модулей:
$ mkdir -p a/b
$ touch a/b/c.py
Убедитесь, что в a
нет других файлов. Запустите интерпретатор Python 3.4 или более поздней версии (например, с python3 -i
) и проверьте результаты следующих операторов:
import a
a ⇒ <module 'a' (namespace)>
a.b ⇒ AttributeError: module 'a' has no attribute 'b'
import a.b.c
a.b ⇒ <module 'a.b' (namespace)>
a.b.c ⇒ <module 'a.b.c' from '/home/cjs/a/b/c.py'>
Модули a
и a.b
являются пакетами (на самом деле, это пакет определенного типа, называемый "пакетом пространства имен", хотя мы не будем беспокоиться об этом здесь). Однако модуль a.b.c
не является пакетом. Мы можем продемонстрировать это, добавив другой файл a/b.py
в структуру каталогов выше и запустив новый интерпретатор:
import a.b.c
⇒ ImportError: No module named 'a.b.c'; 'a.b' is not a package
import a.b
a ⇒ <module 'a' (namespace)>
a.__path__ ⇒ _NamespacePath(['/.../a'])
a.b ⇒ <module 'a.b' from '/home/cjs/tmp/a/b.py'>
a.b.__path__ ⇒ AttributeError: 'module' object has no attribute '__path__'
Python гарантирует, что все родительские модули загружаются до загрузки дочернего модуля. Выше он обнаруживает, что a/
является каталогом и создает пакет пространства имен a
, а a/b.py
является исходным файлом Python, который он загружает и использует для создания (не пакетного) модуля a.b
. На этом этапе у вас не может быть модуля a.b.c
, потому что a.b
не является пакетом и, следовательно, не может иметь подмодулей.
Здесь также видно, что модуль пакета a
имеет атрибут __path__
(пакет должен иметь его), а модуль не 10 * a.b
не имеет.