__init__.py
выполняется при импорте пакета, который его содержит. Но это не твоя проблема. Ваша проблема в том, что импорт модулей всегда абсолютен, если только явно не является относительным. Это означает, что они должны соединяться из некоторого каталога в sys.path
. По умолчанию это включает рабочий каталог, поэтому, когда вы запускаете main.py
из project
, он может найти a_module
и ничего больше.
from sub_module import sub_api
В a_module/__init__.py
не работает, хотя потому что импорт всегда абсолютен, если явно не относителен . Таким образом, импорт говорит: «начиная с некоторого sys.path
root, найдите пакет верхнего уровня с именем sub_module
и импортируйте sub_api
из него». Поскольку такого модуля не существует, вы получаете ошибку. from .sub_module import sub_api
работает, потому что вы выбрали относительный импорт, поэтому он не начинается заново с sys.path
.
Для примера, почему вы это сделаете, я дам вам кое-что, что сломалось в нашем собственном Кодекс за Python 2 дня до абсолютного импорта по умолчанию был законом (from __future__ import absolute_import
включил поведение Py3, как мы его исправили, но, несмотря на то, что говорят документы, он никогда не был включен по умолчанию в Py2, только по умолчанию включено поведение относительного импорта). Наш макет был:
teamnamespace/
module.py
math/
mathrelatedsubmodule.py
othermathsubmodule.py
Теперь, мы невинно подумали, эй, мы поместим все наши пакеты в одно общее пространство имен верхнего уровня, а подпакеты охватывают широкие категории внутри них, и так как у нас было много дополнительные утилиты для основ c математики, мы ставим их под teamnamespace.math
. Проблема заключалась в том, что для не -матических модулей, таких как teamnamespace.module
, когда они делали:
import math # or
from math import ceil
, по умолчанию он относительный поиск и импортировал teamnamespace.math
как math
( абсолютно бесполезный импорт, поскольку это был только пакет пространства имен, все функции были в подмодулях), а не во встроенном модуле math
. Фактически, без поведения Python 3 не было разумного способа получить встроенный модуль math
из модуля в teamnamespace
. Принимая во внимание, что с поведением Python 3 вы можете получить одно или оба (используя псевдонимы одного или другого с помощью as
, без двусмысленности:
# Gets built-in
import math
# Gets teamnamespace.math
from . import math