python 如何动态加载lib中的函数
class TestInstance: def __init__(self): # 初始化库字典,存放找到的库 self.lib = Proxy() # 使用一个代理对象来模拟层级结构 class Proxy: def __init__(self): self._libObjectDictCache = {} def _getLibInstance(self, libName): """ 返回lib的对象 :param libName: :return: """ # 加载projectlib libNameProject, getProjectLibRes = self._load_lib_folder(r'projectLib\projectA', libName) # 加载commonlib,如果projectlib中没有找到对应的库,这里会作为后备 libNameCommon, getCommonLibRes = self._load_lib_folder(r'commonLib', libName) if getProjectLibRes and getCommonLibRes: classes = (libNameProject, libNameCommon)
# 这里会生成有一个新的类,新类先继承project中的类, 在继承 common lib中的类 cls = type('new_'+libName, tuple(classes), {}) elif getCommonLibRes: cls = libNameCommon elif getProjectLibRes: cls = libNameProject else: raise Exception("can not get lib {}".format(libName)) obj = cls() return obj def _load_lib_folder(self, folder_name, libName): import os import importlib # 获取库文件夹的绝对路径 lib_folder_path = os.path.join(os.path.dirname(__file__), folder_name) print("lib_folder_path",lib_folder_path) def import_module_by_path(module_path, module_name): """ 根据给定的完整路径动态导入模块 """ spec = importlib.util.spec_from_file_location(module_name, module_path) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return module # 遍历库文件夹中的所有文件 getLib = False className = None for filename in os.listdir(lib_folder_path): if filename.endswith('.py') and filename != '__init__.py': # 移除文件扩展名,得到库名 lib_module_name = filename[:-3] print("lib_module_name {} libName {}",lib_module_name ,libName) if lib_module_name == libName: modulePath = os.path.join(folder_name,filename) # 使用绝对导入加载库模块 module = import_module_by_path(modulePath, lib_module_name) # 将库模块添加到lib代理对象的层级结构中 #self.lib 现在是module的集合 ,lib.libA这样的调用返回的来是module,而不是class className = getattr(module, lib_module_name) print("className",className, type(className)) # 把module 里面的class 绑定给self.lib, className()是className的对象,className是一个lib 类class # setattr(self.lib, lib_module_name, className()) # 不绑定给self.lib 而是return className() 出来 getLib = True return className, getLib def __getattr__(self, name): try: print("already") obj = self._libObjectDictCache[name] except KeyError: obj = self._getLibInstance(name) self._libObjectDictCache[name] = obj return obj class MyTest(TestInstance): def test_greet(self): # 调用projectlib中的greet函数 self.lib.libA.greet("namename") print("---------------") self.lib.libA.greetB("namename") if __name__ == '__main__': my_test = MyTest() my_test.test_greet()
class Proxy: def __init__(self, _ti, product): rootDir = os.path.dirname(os.path.dirname(__file__)) self._libObjectDictCache = {} self.ti = _ti if product == "productB": self.searchOrder = [os.path.join(rootDir + os.path.sep + 'TestLibrary' + os.path.sep + 'projectLib' + os.path.sep + 'productB'), os.path.join(rootDir + os.path.sep + 'TestLibrary' + os.path.sep + 'projectLib' + os.path.sep + 'productA' ), os.path.join(rootDir + os.path.sep + 'TestLibrary' + os.path.sep + 'commonLib' )] else: self.searchOrder = [os.path.join(rootDir + os.path.sep + 'TestLibrary' + os.path.sep + 'projectLib' + os.path.sep + '{}'.format(product)), os.path.join(rootDir + os.path.sep + 'TestLibrary' + os.path.sep + 'commonLib') + os.path.sep] def _getLibInstance(self, libName): """ 返回lib的对象 :param libName: :return: """ # # 加载projectlib # libNameProject, getProjectLibRes = self._load_lib_folder(r'projectLib\projectA', libName) # # 加载commonlib,如果projectlib中没有找到对应的库,这里会作为后备 # libNameCommon, getCommonLibRes = self._load_lib_folder(r'commonLib', libName) baseClassList = [] for libPath in self.searchOrder: lib, _ = self._load_lib_folder(libPath, libName) if lib is not None: baseClassList.append(lib) baseClass = tuple(baseClassList) # if getProjectLibRes and getCommonLibRes: # classes = (libNameProject, libNameCommon) # # 这里会生成有一个新的类,新类先继承project中的类, 在继承 common lib中的类 # cls = type('new_'+libName, tuple(classes), {}) # elif getCommonLibRes: # cls = libNameCommon # elif getProjectLibRes: # cls = libNameProject # else: # raise Exception("can not get lib {}".format(libName)) print("baseClass",baseClass) if len(baseClass) == 0: raise Exception("can not get lib {}".format(libName)) cls = type('new_' + libName, tuple(baseClass), {}) obj = cls(self.ti) return obj def _load_lib_folder(self, folder_name, libName): import os import importlib # 获取库文件夹的绝对路径 lib_folder_path = os.path.join(os.path.dirname(__file__), folder_name) print("lib_folder_path",lib_folder_path) def import_module_by_path(module_path, module_name): """ 根据给定的完整路径动态导入模块 """ spec = importlib.util.spec_from_file_location(module_name, module_path) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return module # 遍历库文件夹中的所有文件 getLib = False className = None for filename in os.listdir(lib_folder_path): if filename.endswith('.py') and filename != '__init__.py': # 移除文件扩展名,得到库名 lib_module_name = filename[:-3] print("lib_module_name {} libName {}",lib_module_name ,libName) if lib_module_name == libName: modulePath = os.path.join(folder_name,filename) # 使用绝对导入加载库模块 module = import_module_by_path(modulePath, lib_module_name) # 将库模块添加到lib代理对象的层级结构中 #self.lib 现在是module的集合 ,lib.libA这样的调用返回的来是module,而不是class className = getattr(module, lib_module_name) print("className",className, type(className)) # 把module 里面的class 绑定给self.lib, className()是className的对象,className是一个lib 类class # setattr(self.lib, lib_module_name, className()) # 不绑定给self.lib 而是return className() 出来 getLib = True return className, getLib def __getattr__(self, name): try: print("already") obj = self._libObjectDictCache[name] except KeyError: obj = self._getLibInstance(name) self._libObjectDictCache[name] = obj return obj
import os import importlib class TestInstance: def __init__(self): # 初始化库字典,存放找到的库 self.lib = Proxy() # 使用一个代理对象来模拟层级结构 class Proxy: def __init__(self): self._libObjectDictCache = {} def import_module_by_path(self, module_path, module_name): """ 根据给定的完整路径动态导入模块 """ spec = importlib.util.spec_from_file_location(module_name, module_path) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return module def _load_lib_folder(self, libName): classes = [] # 获取库文件夹的绝对路径 for folder_name in [r'projectA',r'commonLib']: lib_folder_path = os.path.join(os.path.dirname(__file__), folder_name) print("lib_folder_path", lib_folder_path) # 遍历库文件夹中的所有文件 getLib = False className = None for filename in os.listdir(lib_folder_path): if filename.endswith('.py') and filename != '__init__.py': # 移除文件扩展名,得到库名 lib_module_name = filename[:-3] # print("lib_module_name {} libName {}",lib_module_name ,libName) if lib_module_name == libName: modulePath = os.path.join(folder_name,filename) # 使用绝对导入加载库模块 module = self.import_module_by_path(modulePath, lib_module_name) # 将库模块添加到lib代理对象的层级结构中 #self.lib 现在是module的集合 ,lib.libA这样的调用返回的来是module,而不是class className = getattr(module, lib_module_name) # 这里的className是类(class),不是class的对象(object) print("className",className, type(className)) # 把module 里面的class 绑定给self.lib, className()是className的对象,className是一个lib 类class # setattr(self.lib, lib_module_name, className()) # 不绑定给self.lib 而是return className() 出来 classes.append(className) if len(classes) == 0: raise Exception("can not get lib {}".format(libName)) classes.append(object) cls = type('New_' + libName, tuple(classes), {}) # print("cls.__mro__", cls.__mro__) obj = cls() return obj def __getattr__(self, name): try: obj = self._libObjectDictCache[name] print("already") except KeyError: obj = self._load_lib_folder(name) self._libObjectDictCache[name] = obj return obj class MyTest(TestInstance): def test_greet(self): # 调用projectlib中的greet函数 self.lib.libA.greet("namename") print("---------------") self.lib.libA.greetB("namename") self.lib.libB.greet("namename") self.lib.libC.greetB("namename") # self.lib.libD.greetB("namename") if __name__ == '__main__': my_test = MyTest() my_test.test_greet()
原创代码,未经允许不得转载