我有一个包含类C1, C2, CInvalid3, C4
的包,它们在不同的子模块中定义。
my_package/
__init__.py
sub_package1/
__init__.py
sub_module1.py # contains C1, C2
sub_package2/
__init__.py
sub_module2.py # contains CInvalid3, C4
给定一个包含某个类名的字符串,我想初始化相应的类。例如,
some_valid_class_name = 'C1'
some_valid_class = all_valid_classes[some_valid_class_name]()
目前,我在all_classes.py
下创建了一个模块my_package
,其中包含
all_valid_classes = {} # I want the dict contain C1, C2 and C4
def this_is_a_valid_class(cls):
all_valid_classes[cls.__name__] = cls
return cls
在sub_module1.py
和sub_module2.py
中,我使用
from my_package.all_classes import this_is_a_valid_class
@this_is_a_valid_class
class C1(object):
pass
并添加
from .sub_package1 import sub_module1
from .sub_package2 import sub_module2
到my_package/__init__.py
。
有没有更好的方法来处理这个问题?我导入my_package/__init__.py
中的所有内容。当我添加新的sub_package3.sub_module3.C99
时,我需要记住将from .sub_package3 import sub_module3
添加到my_package/__init__.py
。我不认为这些是好主意。
答案 0 :(得分:1)
要获得您正在寻找的内容,您可以做的是标记具有类属性的有效类:
class C1(object):
_valid = True
然后动态导入包中的所有模块,在此过程中将有效类分别存储在all_valid_classes
字典中。
关键是你必须导入你想要使用的所有类的模块,所以你可以手动(正如你现在所做)或动态地(在其中找到模块的文件名)包裹并导入它们。)
这个片段展示了这个概念(请注意它真的很难看,仅用于概念验证,我匆忙组装它!)。它将放在您的my_module/__init__.py
文件中:
import os
import fnmatch
from importlib import import_module
from types import TypeType
# dictionary with all valid classes
all_valid_classes = {}
# walk directory and load modules dynamically
this_path = os.path.dirname(__file__)
modules = []
for root, dirnames, filenames in os.walk(this_path):
for filename in fnmatch.filter(filenames, '*.py'):
# avoid this file importing itself
full_path = os.path.join(root, filename)
if full_path == os.path.join(this_path, '__init__.py'):
continue
# convert the filename to the module name
trimmed_path = full_path[len(this_path) + 1:-3]
module_name = trimmed_path.replace('/', '.')
# import the module
module = import_module('%s.%s' % (__name__, module_name))
# find valid classes (classes with a '_valid = True' attribute
for item_name in dir(module):
item = getattr(module, item_name)
if type(item) == TypeType:
try:
valid_attr = getattr(item, '_valid')
if valid_attr is True:
all_valid_classes[item_name] = item
except AttributeError:
pass
导入my_module
后,all_valid_classes
将包含C1
,C2
和C4
(前提是它们标有_valid = True
)。< / p>
PS。但是请注意,我会亲自手动进行导入,在我看来它更加诡计多端。