Подтвердить что ты не робот

Относительный импорт пакета __init__.py

Предположим, что у меня есть пакет, содержащий два подмодуля, а также значительную часть кода в __init__.py:

pkg/__init__.py
pkg/foo.py
pkg/bar.py

и, чтобы облегчить планируемое будущее рефакторинг, я хочу, чтобы компоненты пакета использовали исключительно относительный импорт для ссылки друг на друга. В частности, import pkg никогда не должно появляться.

Из foo.py я могу сделать

from __future__ import absolute_import
from . import bar

чтобы получить доступ к модулю bar.py и наоборот.

Вопрос в том, что я пишу для импорта __init__.py таким образом? Я хочу точно такой же эффект, как import pkg as local_name, только без указания абсолютного имени pkg.

#import pkg as local_name
from . import ??? as local_name

ОБНОВЛЕНИЕ: Вдохновленный ответом maxymoo, я попробовал

from . import __init__ as local_name

Это не устанавливает local_name в модуль, определенный __init__.py; вместо этого он получает то, что кажется оберткой связанного метода для метода __init__ этого модуля. Я полагаю, я мог бы сделать

from . import __init__ as local_name
local_name = local_name.__self__

чтобы получить то, что я хочу, но (a) yuck, и (b) это заставляет меня беспокоиться о том, что модуль не был полностью инициализирован.

Ответы должны работать как на Python 2.7, так и на Python 3.4 +.

Да, вероятно, было бы лучше выбить __init__.py и просто перегрузить материал из подмодулей, но этого пока не может быть.

4b9b3361

Ответ 1

Ничего особенного в dunders (они просто обескуражены при написании собственных имен модулей/функций); вы должны просто быть в состоянии сделать

from .__init__ import my_function as local_name

Ответ 2

  • python2 и python3 (использует обескураженный __import__):

    • из модуля 1-го уровня (pkg.foo, pgk.bar,...):

      local_name = __import__("", globals(), locals(), [], 1)
      
    • из модуля в подпапке (pkg.subpkg.foo,...):

      local_name = __import__("", globals(), locals(), [], 2)
      
  • только python3 *:

    • От pkg.foo или pkg.bar:

      import importlib
      local_name = importlib.import_module("..", __name__)
      
    • От pkg.subpkg.baz:

      import importlib
      local_name = importlib.import_module("...", __name__)
      

* import_module на python2 пытается загрузить pkg. в этом случае, к сожалению.