How to load all modules in a folder?

后端 未结 18 1628
失恋的感觉
失恋的感觉 2020-11-22 05:37

Could someone provide me with a good way of importing a whole directory of modules?
I have a structure like this:

/Foo
    bar.py
    spam.py
    eggs.py         


        
相关标签:
18条回答
  • 2020-11-22 06:04

    Add the __all__ Variable to __init__.py containing:

    __all__ = ["bar", "spam", "eggs"]
    

    See also http://docs.python.org/tutorial/modules.html

    0 讨论(0)
  • 2020-11-22 06:04

    When from . import * isn't good enough, this is an improvement over the answer by ted. Specifically, the use of __all__ is not necessary with this approach.

    """Import all modules that exist in the current directory."""
    # Ref https://stackoverflow.com/a/60861023/
    from importlib import import_module
    from pathlib import Path
    
    for f in Path(__file__).parent.glob("*.py"):
        module_name = f.stem
        if (not module_name.startswith("_")) and (module_name not in globals()):
            import_module(f".{module_name}", __package__)
        del f, module_name
    del import_module, Path
    

    Note that module_name not in globals() is intended to avoid reimporting the module if it's already imported, as this can risk cyclic imports.

    0 讨论(0)
  • 2020-11-22 06:05

    Anurag's example with a couple of corrections:

    import os, glob
    
    modules = glob.glob(os.path.join(os.path.dirname(__file__), "*.py"))
    __all__ = [os.path.basename(f)[:-3] for f in modules if not f.endswith("__init__.py")]
    
    0 讨论(0)
  • 2020-11-22 06:07

    Expanding on Mihail's answer, I believe the non-hackish way (as in, not handling the file paths directly) is the following:

    1. create an empty __init__.py file under Foo/
    2. Execute
    import pkgutil
    import sys
    
    
    def load_all_modules_from_dir(dirname):
        for importer, package_name, _ in pkgutil.iter_modules([dirname]):
            full_package_name = '%s.%s' % (dirname, package_name)
            if full_package_name not in sys.modules:
                module = importer.find_module(package_name
                            ).load_module(full_package_name)
                print module
    
    
    load_all_modules_from_dir('Foo')
    

    You'll get:

    <module 'Foo.bar' from '/home/.../Foo/bar.pyc'>
    <module 'Foo.spam' from '/home/.../Foo/spam.pyc'>
    
    0 讨论(0)
  • 2020-11-22 06:08

    List all python (.py) files in the current folder and put them as __all__ variable in __init__.py

    from os.path import dirname, basename, isfile, join
    import glob
    modules = glob.glob(join(dirname(__file__), "*.py"))
    __all__ = [ basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')]
    
    0 讨论(0)
  • 2020-11-22 06:09

    Update in 2017: you probably want to use importlib instead.

    Make the Foo directory a package by adding an __init__.py. In that __init__.py add:

    import bar
    import eggs
    import spam
    

    Since you want it dynamic (which may or may not be a good idea), list all py-files with list dir and import them with something like this:

    import os
    for module in os.listdir(os.path.dirname(__file__)):
        if module == '__init__.py' or module[-3:] != '.py':
            continue
        __import__(module[:-3], locals(), globals())
    del module
    

    Then, from your code do this:

    import Foo
    

    You can now access the modules with

    Foo.bar
    Foo.eggs
    Foo.spam
    

    etc. from Foo import * is not a good idea for several reasons, including name clashes and making it hard to analyze the code.

    0 讨论(0)
提交回复
热议问题