Search code examples
pythonimportmodule

How to import all submodules?


I have a directory structure as follows:

| main.py
| scripts
|--| __init__.py
   | script1.py
   | script2.py
   | script3.py

In main.py, if I import scripts, this apparently does not allow me to use scripts.script1. I know I can use from scripts import * to access the modules in the scripts package, but then I can only use them directly as scripts1, scripts2 etc.

How can I write the code so that I can refer to scripts.script1 inside main.py?

I tried using pkgutils.walk_packages, as well as the __all__ attribute of the package, to get the submodule names, but I couldn't figure out a way to use those strings to do the import.


Solution

  • Edit: Here's one way to recursively import everything at runtime...

    (Contents of __init__.py in top package directory)

    import pkgutil
    
    __all__ = []
    for loader, module_name, is_pkg in pkgutil.walk_packages(__path__):
        __all__.append(module_name)
        _module = loader.find_module(module_name).load_module(module_name)
        globals()[module_name] = _module
    

    I'm not using __import__(__path__+'.'+module_name) here, as it's difficult to properly recursively import packages using it. If you don't have nested sub-packages, and wanted to avoid using globals()[module_name], though, it's one way to do it.

    There's probably a better way, but this is the best I can do, anyway.

    Original Answer (For context, ignore othwerwise. I misunderstood the question initially):

    What does your scripts/__init__.py look like? It should be something like:

    import script1
    import script2
    import script3
    __all__ = ['script1', 'script2', 'script3']
    

    You could even do without defining __all__, but things (pydoc, if nothing else) will work more cleanly if you define it, even if it's just a list of what you imported.