我有一个具有此层次结构的项目
tasker/
table/
__init__.py
user.py
task.py
...
__init__.py
tasker.py
table
文件夹中的每个文件(__init__.py
除外)都包含一个与文件名同名的类,但第一个字母大写。我想调用并实例化table
中tasker.py
文件夹中的每个类。我可以通过写
import table
在tasker.py
内。但是,事实证明我必须编写例如
table.user.User()
实例化user.py
内的类,看起来很丑陋。有什么办法让我只输入
user.User()
甚至更好,
User()
实例化那些类?
注意:table
文件夹中的每个文件都会被动态更改。我可以在table
文件夹中添加或删除文件。
答案 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 *