如何递归导入模块中的所有类?

问题描述 投票:0回答:2

是否可以递归地使用

__all__
? 这会在
__all__
...

中导入模块
from mypkg import *

但不是递归的。

尝试将所有内容放入

__all__
__init__.py
内)似乎也没有用:

from pathlib import Path

# List all python (.py) files in the current folder and put them as __all__
fs = [f for f in Path('mypkg/').rglob('*.py') if not f.name.endswith('__init__.py')]
__all__ = [str(f).replace('/','.')[:-3][5:] for f in fs]

自从...

from mypkg import *

包中第一个文件夹的结果为

AttributeError: module 'mypkg' has no attribute 'module1.file1'

python-3.x module
2个回答
0
投票

通过将其添加到

__init__.py
来解决。对于大多数情况来说可能不是最好的方法,但对于我的用例来说已经足够了。

from pathlib import Path

# Include all classes when 'from mypkg import *' is called. 
fs = [f for f in Path('mypkg').rglob('*.py') if not f.name.startswith('_')]

for f in [str(f).replace('/', '.')[:-3] for f in fs]:
    statement = f'from {f} import *'
    exec(statement)

0
投票
def get_classes_from_package_recursively(package: str) -> list[type]:
    """Return a list of classes inside a given package (recurse thorugh any sub-packages).

    Keyword arguments:
    package -- package represented as a string. Must not be relative.
    """
    classes_in_package = []
    # Go through the modules in the package
    for _importer, module_name, is_package in pkgutil.iter_modules(importlib.import_module(package).__path__):
        full_module_name = f"{package}.{module_name}"
        # Recurse through any sub-packages
        if is_package:
            classes_in_subpackage = get_classes_from_package_recursively(package=full_module_name)
            classes_in_package.extend(classes_in_subpackage)

        # Load the module for inspection
        module = importlib.import_module(full_module_name)

        # Iterate through all the objects in the module and
        # using the lambda, filter for class objects and only objects that exist within the module
        for _name, obj in inspect.getmembers(
            module,
            lambda member, module_name=full_module_name: inspect.isclass(member) and member.__module__ == module_name,
        ):
            classes_in_package.append(obj)
    return classes_in_package

如何使用上面的类的示例:

my_classes = get_classes_from_package_recursively(package="src.database.models")

my_classes
现在看起来像这样
[MyModel1, MyModel2, MyModel3, etc...]

© www.soinside.com 2019 - 2024. All rights reserved.