如何调用包内的所有模块?

时间:2018-06-06 04:14:38

标签: python python-module

我有一个具有此层次结构的项目

tasker/
        table/
                __init__.py
                user.py
                task.py
                ...
        __init__.py
        tasker.py

table文件夹中的每个文件(__init__.py除外)都包含一个与文件名同名的类,但第一个字母大写。我想调用并实例化tabletasker.py文件夹中的每个类。我可以通过写

来做到这一点
import table

tasker.py内。但是,事实证明我必须编写例如

table.user.User()

实例化user.py内的类,看起来很丑陋。有什么办法让我只输入

user.User()

甚至更好,

User()

实例化那些类?

注意:table文件夹中的每个文件都会被动态更改。我可以在table文件夹中添加或删除文件。

3 个答案:

答案 0 :(得分:2)

我建议自动完成大部分工作。您可以在tasker.table.__init__

中注册您感兴趣的模块
table_registry = ['user', 'task', ...]

此时您无需导入任何内容,我不建议使用__all__,因为它完全用于不同目的。使用手动创建的列表的优点是您的包可以包含其他模块而不受任何干扰。

现在tasker.tasker可以动态完成所有工作:

from .table import table_registry
from importlib import import_module

pkg = 'tasker.table'
for name in table_registry:
    mod = import_module('.' + name, package=pkg)
    name = name.titlecase()
    # Check if module contains uppercased class name
    if hasattr(mod, name):
        cls = getattr(mod, name)
        # Check if it's a class
        if isinstance(cls, type):
            # Assign to current module
            globals()[name] = cls

del name, mod, cls

如果您不想手动注册感兴趣的模块,可以使用pkgutil中的实用程序动态发现它们。在此版本中,tasker.table.__init__可以保持为空。 tasker.tasker将获得如下模块列表:

from pkgutil import walk_packages
from importlib import import_module

for info in walk_packages(tasker.table.__path__, prefix='tasker.table.'):
    if info.ispkg: continue
    mod = import_module(info.name)
    name = info.name.split('.')[-1].titlecase()
    if hasattr(mod, name):
        ...

代码的其余部分与手动版本相同。此版本将递归到它找到的任何子包中。只要您不对__path__属性做任何疯狂的事情,它就能正常工作。

答案 1 :(得分:0)

这可能有效

from table import user

user.User()

答案 2 :(得分:0)

您可以使用星号一次导入包内的所有模块:

from table import *