是否可以递归地使用
__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'
。
通过将其添加到
__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)
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...]