动态加载py文件中的类
开发过程中有很多需要动态的导入py文件中的类,有点类似与java的反射。
本代码样例是自动加载child_module文件夹下面的所有包含TypeA字样的类,并返回类中的name和类对象的dict。
创建文件夹(文件和文件夹一览)
test_aotu_import(文件夹)
-main.py
-child_module(文件夹)
--__init__.py
--sub_class_1.py
--sub_class_2.py
主文件夹下包含main.py和child_module文件夹,然后child_module文件夹下包含init.py、sub_class_1.py、sub_class_2.py。
main.py
import pkgutil
import os
def find_database_access_class(
parent_module_name : str ,
module_dir : str,
sub_class :str = "TypeA"
) -> dict:
"""
查找moduel_dir下的所有py文件的所有类,过滤非
参数:
parent_module_name:父模块路径
module_dir:需要导入的模块名称(就是需要查找子类文件的文件夹)
sub_class:校验类的名字中是否包含TypeA字样
返回:
{
"类name: 类对象
}
"""
base_dir = os.path.dirname(__file__)
#如果是main执行上面的os.path.dirname,返回的是空,则需要调用abspath获取绝对路径
if not base_dir:
base_dir = os.path.dirname(os.path.abspath(__file__))
modules = pkgutil.iter_modules([base_dir+"/"+module_dir])
found_modules = []
for x, sub_file_name, _ in modules:
module_name = parent_module_name + "." + sub_file_name
found_module = x.find_module(module_name).load_module(module_name)
found_modules.append(found_module)
found_type_a_modules = {}
for module in found_modules:
attrs = list(dir(module))
#校验其类名是否包含TypeA
type_a_class = [ x for x in attrs if sub_class in x ]
for class_name in type_a_class:
class_ins = getattr(module, class_name)
#校验类中是否包含类name变量
if hasattr(class_ins, "name"):
found_type_a_modules[getattr(class_ins, "name")] = class_ins
return found_type_a_modules
if __name__=="__main__":
found_class_dict = find_database_access_class("child_module", "child_module")
for class_name, class_ in found_class_dict.items():
print(f"class_name:{class_name}", class_().say())
child_module->sub_class_1.py
class ATypeA:
name = "ATypeA"
def say(self):
return " I'm ATypeA"
class BTypeB:
name = "BTypeB"
def say(self):
return " I'm BTypeB"
class CTypeA:
name = "CTypeA"
def say(self):
return "I'm CTypeA"
child_module->sub_class_2.py
class DTypeA:
name = "DTypeA"
def say(self):
return " I'm DTypeA on sub_class_2"
运行效果:
class_name:ATypeA I'm ATypeA
class_name:CTypeA I'm CTypeA
class_name:DTypeA I'm DTypeA on sub_class_2