# testInstance.py
# 导入需要的模块
import importlib # 导入模块以动态加载库中的类和函数
import sys # 导入系统模块,用于操作Python解释器的参数和变量
import os
import pkgutil
# 定义TestInstance类
class TestInstance:
# 初始化方法,当创建TestInstance对象时调用
def __init__(self, projectName):
# 初始化实例变量projectName,存储项目名称
self.projectName = projectName
# 调用load_libraries方法加载库,并将结果存储在self.lib中
self.lib = self.load_libraries()
# 定义load_libraries方法,用于加载库
def list_submodules(self,package_path):
"""递归地列出给定包路径下的所有子模块"""
all_submodules = []
# 遍历包路径下的所有文件/目录
for importer, modname, ispkg in pkgutil.iter_modules([package_path]):
full_modname = modname
module_path = os.path.join(package_path, modname)
# 如果是子包,则递归调用list_submodules
if ispkg:
# 构建子包的完整路径
subpackage_path = os.path.join(module_path, '__init__.py')
# 递归查找子包下的子模块
submodules = self.list_submodules(subpackage_path)
# 添加子模块名称到结果列表,同时保留子包的路径
all_submodules.extend([full_modname + '.' + submodule for submodule in submodules])
else:
# 添加非包模块的完整名称
all_submodules.append(full_modname)
return all_submodules
def load_libraries(self):
# 导入配置模块
import libconfig # 假设存在一个名为libconfig的模块,其中包含库的加载顺序等信息
# 初始化一个空字典,用于存储库中的类和函数
libraries = {}
# 将库路径添加到sys.path,以便Python能够找到这些库
# sys.path.append(r"C:\Users\15773\Desktop\文心一言\新建文件夹\test_library\projectLib") # 添加项目库路径
# sys.path.append(r"C:\Users\15773\Desktop\文心一言\新建文件夹\test_library\commonLib") # 添加通用库路径
print("sys.path",sys.path)
# 按照配置模块中指定的顺序加载库
root = r"C:\Users\15773\Desktop\文心一言\新建文件夹\test_library"
for lib_name in libconfig.libraries_order: # 遍历库名列表
# sys.path.insert(0,os.path.join(root, lib_name))
libPath = os.path.abspath(os.path.join(root, lib_name))
print("libPath",libPath,lib_name)
allPac = self.list_submodules(libPath)
print("allPac",allPac)
# 动态导入库模块
for library in allPac:
print("library",library)
module = importlib.import_module(library) # 使用importlib导入库模块
print("-----",dir(module))
print("module.__file__",module.__file__)
print([attr_name for attr_name in dir(module) if not attr_name.startswith('_')])
# 将库模块中的非私有属性和方法添加到libraries字典中
libraries.update(
{attr_name: getattr(module, attr_name) for attr_name in dir(module) if not attr_name.startswith('_')})
print("libraries",libraries)
# 创建一个类似命名空间的类,用于持有所有库中的类和函数
class LibraryNamespace:
# 定义__getattr__方法,当尝试访问不存在的属性时调用
def __getattr__(self, item):
print("--item",item)
# 首先检查项目库中是否存在该属性
if item in libraries:
print("item in lib-------------",item,libraries)
# return libraries[item] # 如果存在,直接返回对应的类或函数
tempInstance = libraries[item]() # 如果存在,直接返回对应的类或函数
return tempInstance
# 如果在项目库中找不到,尝试从commonlib库中导入
commonlib_module = importlib.import_module(f"commonlib.{item}") # 动态导入commonlib中的模块或函数
tempInstance = commonlib_module()
print("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&")
# return getattr(commonlib_module, item) # 返回commonlib中的类或函数
return getattr(tempInstance, item) # 返回commonlib中的类或函数
# 创建一个LibWrapper类,用于包装LibraryNamespace,并为其添加一个lib属性
class LibWrapper:
def __init__(self, namespace):
# print("namespace",namespace)
# 在LibWrapper实例初始化时,将LibraryNamespace实例赋值给lib属性
self.lib = namespace
# 返回LibWrapper的实例,其中包含了LibraryNamespace
# return LibWrapper(LibraryNamespace())
# print("namespace",LibraryNamespace)
return LibraryNamespace()
# 如果该脚本被直接执行(而不是作为模块导入),则执行以下代码
if __name__ == '__main__':
# 假设当前项目名称为"projectlib"
projectName = "projectA"
# 创建TestInstance对象
test = TestInstance(projectName)
# print("test.lib",test.lib)
# 调用lib.libA.greet方法,并传递参数"world"
# 由于使用了__getattr__,即使libA或greet不存在,也不会立即抛出异常,而是会尝试从commonlib中导入
print(test.lib.libA.greet("hello world"))
print(test.lib.libA.greetB("BBB"))