Hide external modules when importing a module (e.g. regarding code-completion)

Each Answer to this Q is separated by one/two green lines.

I have several modules in one package (a kind of a toolkit), which I use in my projects. The structure looks like this:

the_toolkit:
    __init__.py
    basic_io.py
    simple_math.py
    matrix_kit.py
    ...

Now when I use IPython or the code completion in VIM after importing a module from the package with

from the_toolkit import matrix_kit

I get a bunch of modules/functions which matrix_kit.py imports (array, math, log, loggin, format_exc, etc.), along with the actual functions which matrix_kit defines.
How can I filter out everything else, since I’m not interested in math or array in a code completion of the matrix_kit module?

The __init__.py is empty as suggested by many pythonistas, or is it the way to do it?

I had the same problem, and solved it by adding a leading underscore to all my imports. It doesn’t look brilliant, but it achieves what you’re after.

from __future__ import division as _division
import numpy as _np
import pandas as _pd

Only the stuff that starts without an underscore is imported when you import the module using from .. import *. or when you use tab-completion in IPython or spyder.

I’ve come to like and use this approach. Starting with your project structure, we will hide all the content of matrix_kit that you don’t want to show.

the_toolkit:
    __init__.py
    basic_io.py
    simple_math.py
    matrix_kit.py
    ...

Move matrix_kit.py into a package with the same name, and place one underscore in the beginning of the module’s name:

the_toolkit:
    __init__.py
    basic_io.py
    simple_math.py
    matrix_kit:
        __init__.py
        _matrix_kit.py
    ...

Now in _matrix_kit.py add a global variable __all__ = [...] listing the names of all functions/classes/variables you want to be visible. Then, add the following line to matrix_kit/__init__.py:

from ._matrix_kit import *

It will only import the stuff listed in the __all__ attribute of the module. Then, while importing matrix_kit like you’ve done before, you will actually import the __init__.py and its content.

An alternative solution I came up with is to implement a short API class in the __init__ file which can make use of the __all__ variable (which may already be defined for import * purposes). Something like this in __init__.py:

import matrix_kit

class _matrix_kit_API:
    def __init__(self):
        for func in matrix_kit.__all__:
            setattr(self, func, eval(f"matrix_kit.{func}"))

matrix_kit = _matrix_kit_API()

you may get some mileage out of __all__


The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .