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()

 

 

 

原创代码,未经允许不得转载

posted @ 2024-04-27 20:47  朵朵奇fa  阅读(56)  评论(0编辑  收藏  举报