How to import all submodules?

前端 未结 9 1400
盖世英雄少女心
盖世英雄少女心 2020-11-27 16:57

I have a directory structure as follows:

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

From ma

9条回答
  •  我在风中等你
    2020-11-27 17:47

    I've played around with Joe Kington's Answer and have built a solution that uses globals and get/setattr and thus doesn't need eval. A slight modification is that instead of directly using the packages __path__ for walk_packages, I use the packages parent directory and then only import modules starting with __name__ + ".". This was done to reliably get all subpackages from walk_packages - in my use case I had a subpackage named test which caused pkgutil to iterate over the test package from python's library; furthermore, using __path__ would not recurse into the packages subdirectories. All these issues were observed using jython and python2.5, the code below is only tested in jython thus far.

    Also note that OPs question only talks about importing all modules from a package, this code recursively imports all packages too.

    from pkgutil import walk_packages
    from os import path
    
    __all__ = []
    __pkg_prefix = "%s." % __name__
    __pkg_path = path.abspath(__path__[0]).rsplit("/", 1)[0] #parent directory
    
    for loader, modname, _ in walk_packages([__pkg_path]):
        if modname.startswith(__pkg_prefix):
            #load the module / package
            module = loader.find_module(modname).load_module(modname)
            modname = modname[len(__pkg_prefix):] #strip package prefix from name
            #append all toplevel modules and packages to __all__
            if not "." in modname:
                __all__.append(modname)
                globals()[modname] = module
            #set everything else as an attribute of their parent package
            else:
                #get the toplevel package from globals()
                pkg_name, rest = modname.split(".", 1)
                pkg = globals()[pkg_name]
                #recursively get the modules parent package via getattr
                while "." in rest:
                    subpkg, rest = rest.split(".", 1)
                    pkg = getattr(pkg, subpkg)
                #set the module (or package) as an attribute of its parent package
                setattr(pkg, rest, module)
    

    As a future improvement I'll try to make this dynamic with a __getattr__ hook on the package, so the actual modules are only imported when they are accessed...

提交回复
热议问题