Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 401
zwol Avatar asked Mar 05 '17 23:03

zwol


People also ask

What is __ init __ py in Python package?

The __init__.py files are required to make Python treat directories containing the file as packages. This prevents directories with a common name, such as string , unintentionally hiding valid modules that occur later on the module search path.

How do you use relative import in Python?

Relative imports use dot(.) notation to specify a location. A single dot specifies that the module is in the current directory, two dots indicate that the module is in its parent directory of the current location and three dots indicate that it is in the grandparent directory and so on.

Does init py import all modules?

We can turn this directory into a package by introducing __init__.py file within utils folder. Within __init__.py , we import all the modules that we think are necessary for our project.

Should I use relative or absolute imports Python?

Note that relative imports are based on the name of the current module. Since the name of the main module is always “main”, modules intended for use as the main module of a Python application must always use absolute imports.


2 Answers

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
like image 192
maxymoo Avatar answered Oct 13 '22 04:10

maxymoo


  • 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.

like image 20
mata Avatar answered Oct 13 '22 06:10

mata