如何调用包内的所有模块?
How to Call All Modules inside Package?
我有一个具有此层次结构的项目
tasker/
table/
__init__.py
user.py
task.py
...
__init__.py
tasker.py
table
文件夹中的每个文件(__init__.py
除外)都包含一个与文件名同名的 class,只是第一个字母大写。我想调用并实例化 tasker.py
中 table
文件夹中的每个 class。我可以写
import table
里面 tasker.py
。但是,事实证明我必须写例如
table.user.User()
在user.py
里面实例化class,看起来很丑。有什么方法可以让我至少输入
user.User()
甚至更好,
User()
实例化那些 classes?
注意:table
文件夹中的每个文件都是动态更改的。我可能会在 table
文件夹中添加或删除文件。
这可能有效
from table import user
user.User()
我建议自动完成大部分工作。您可以在 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__
属性做任何疯狂的事情,它就会正常工作。
您可以使用星号一次性导入包内的所有模块:
from table import *
我有一个具有此层次结构的项目
tasker/
table/
__init__.py
user.py
task.py
...
__init__.py
tasker.py
table
文件夹中的每个文件(__init__.py
除外)都包含一个与文件名同名的 class,只是第一个字母大写。我想调用并实例化 tasker.py
中 table
文件夹中的每个 class。我可以写
import table
里面 tasker.py
。但是,事实证明我必须写例如
table.user.User()
在user.py
里面实例化class,看起来很丑。有什么方法可以让我至少输入
user.User()
甚至更好,
User()
实例化那些 classes?
注意:table
文件夹中的每个文件都是动态更改的。我可能会在 table
文件夹中添加或删除文件。
这可能有效
from table import user
user.User()
我建议自动完成大部分工作。您可以在 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__
属性做任何疯狂的事情,它就会正常工作。
您可以使用星号一次性导入包内的所有模块:
from table import *