zwol
zwol

Reputation: 140540

Relative import of package __init__.py

Suppose I have a package containing two submodules and also a substantial amount of code in __init__.py itself:

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

and, to make planned future refactorings easier, I want components of the package to exclusively use relative imports to refer to each other. In particular, import pkg should never appear.

From foo.py I can do

from __future__ import absolute_import
from . import bar

to get access to the bar.py module, and vice versa.

The question is, what do I write to import __init__.py in this manner? I want exactly the same effect as import pkg as local_name, only without having to specify the absolute name pkg.

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

UPDATE: Inspired by maxymoo's answer, I tried

from . import __init__ as local_name

This does not set local_name to the the module defined by __init__.py; it instead gets what appears to be a bound method wrapper for the __init__ method of that module. I suppose I could do

from . import __init__ as local_name
local_name = local_name.__self__

to get the thing I want, but (a) yuck, and (b) this makes me worry that the module hasn't been fully initialized.

Answers need to work on both Python 2.7 and Python 3.4+.

Yes, it would probably be better to hollow out __init__.py and just have it reexport stuff from the submodules, but that can't happen just yet.

Upvotes: 17

Views: 3483

Answers (2)

mata
mata

Reputation: 69012

  • python2 and python3 (uses the discouraged __import__):

    • from 1st level module (pkg.foo, pgk.bar, ...):

      local_name = __import__("", globals(), locals(), [], 1)
      
    • from module in subpackage (pkg.subpkg.foo, ...):

      local_name = __import__("", globals(), locals(), [], 2)
      
  • python3 only*:

    • From pkg.foo or pkg.bar:

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

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

*import_module on python2 tries load pkg. in this case, unfortunately.

Upvotes: 1

maxymoo
maxymoo

Reputation: 36545

There's nothing special about the dunders (they're just discouraged when writing your own module/function names); you should just be able to do

from .__init__ import my_function as local_name

Upvotes: 4

Related Questions