import importlib
import pkgutil


def _walk_modules(path):
    """
    Loads a module and all its submodules from the given module path and
    returns them. If *any* module throws an exception while importing, that
    exception is thrown back.
    """

    # Support for namespace packages is added. See PEP 420.
    # Namespace packages are a mechanism for splitting a single Python package across multiple directories on disk.
    # When interpreted encounter with non-empty __path__ attribute it adds modules found in those locations
    # to the current package.

    mods = []
    mod = importlib.import_module(path)
    mods.append(mod)
    if hasattr(mod, '__path__'):
        for _, subpath, ispkg in pkgutil.iter_modules(mod.__path__):
            fullpath = path + '.' + subpath
            if ispkg:
                mods += _walk_modules(fullpath)
            else:
                submod = importlib.import_module(fullpath)
                mods.append(submod)
    return mods