最近做python项目用到了动态加载模块这个技术,需求很明了。
0、适用于热执行,在特定的场景调用(比如安装包里面提供了install.so,用于安装安装包本身)
1、不干扰已经存在的模块,就算名字相同
2、开袋即食,用完回收,不长久持有引用
3、需要兼容.pyd(windows)、.so(linux)
4、使用完整的绝对路径,不依赖sys.path
5、需要兼容3.5+,目前我用的是python3.8
百度就不用说了,一大堆import的初级用法,没有相关的文献可以参考,改变阵地去Google搜索了一番,发现.py的加载和.pyd的加载大有不同,具体看文章(第12个回答) -> 堆栈论坛
具体的不同之处就是
ExtensionFileLoader 用于加载扩展文件,也就是我们编译后的.so或者.pyd
SourcelessFileLoader 用于加载源文件,就是我们经常看见的.py源文件
然后,废话不多说,给一个开袋即食(相对,版本还是要匹配的)的函数:
@staticmethod
def path_import(file):
"""
导入模块
:param file:
:return:
"""
print("\n******************* 开始动态加载模块 *************************")
loader_details = (
importlib.machinery.ExtensionFileLoader,
importlib.machinery.EXTENSION_SUFFIXES
)
tools_finder = importlib.machinery.FileFinder(os.path.dirname(file), loader_details)
print("FileFinder: ", tools_finder)
toolbox_specs = tools_finder.find_spec(os.path.basename(file).split(".")[0])
print("find_spec: ", toolbox_specs)
toolbox = importlib.util.module_from_spec(toolbox_specs)
print("module: ", toolbox)
toolbox_specs.loader.exec_module(toolbox)
print("导入成功 path_import(): ", toolbox)
print("检查sys中是否包含了此模块: ", toolbox in sys.modules)
print("******************* 动态加载模块完成 *************************\n")
return toolbox
需要导入的库:
import os
import importlib.machinery
import importlib.util
上面书写的函数经过验证是可用的,当然,我的版本是py3.8,各位朋友要看清楚自己的版本,版本不适用的话要去堆栈那里看看自己的需求的对应实现(有较低版本的兼容代码)。
无图无真相,给大家贴一动态加载.so成功的截图:
需求记录完成,希望可以帮到大家。