python/Django 动态加载(调用)代码文件(模块和类)

项目需求

最近在做一个Django项目,需要实现可以自己上传代码,来实现某些功能;类似于插件形式,项目的功能是由我上传的代码来实现。但是不影响项目的运行。

解决方案

这里有两个解决方案,

1、可执行文件

就是把要上传的代码封装成可执行文件,就是可以在命令行直接执行的文件,上传到项目中,这样就可以在已经运行的项目中直接执行代码。
缺点:就是传递参数只能通过cmd或者配置文件。也可直连数据库,这样就比较麻烦了。

2、动态加载代码

这个就是今天要说的,动态加载代码,可以直接把上传的代码文件(模块和类)加载到项目中直接调用执行。

动态加载

技术方案

1、项目中代码的目录结构

 ├─Item						# 项目,主目录
 │  ├─compose				# 动态加载功能
 │  │  ├─initiator.py		# 动态加载代码,调用上传程序
 │  │  ├─plugins			# 上传代码的目录
 │  │  │   ├─add_name.py	# 上传的代码,用来动态加载
 │  │  │   └─add_name2.py	# 上传的代码,用来动态加载

2、代码
initiator.py 中代码如下:


class LazyImport(object):
    """
    动态导入模块
    """
    def __init__(self, module_name, module_class):
        """
        :param module_name:
        :param module_class:
        :return: 等同于 form module_name import module_class
        """
        self.module_name = module_name
        self.module_class = module_class
        self.module = None

    def __getattr__(self, name):
        if self.module is None:
            self.module = __import__(self.module_name, fromlist=[self.module_class])
        return getattr(self.module, name)


def test(filename, clsname):
    importmodule = LazyImport("compose.plugins." + filename, clsname)  # 导入classname模块
    is_true = hasattr(importmodule, clsname)  # 检查classname类是否在classname模块中
    if is_true:
        classname = getattr(importmodule, clsname)
        # 传递参数
        obj = classname('大花', '猪')  # 实例化classname类
        mtd = getattr(obj, 'run')
        dd = mtd()  # 调用run方法,接收return返回值
        print(dd)

add_name.py 代码

class add_name(object):
    def __init__(self, name, genre):
        self.name = name
        self.genre = genre

    def run(self):
        print("名称:{},类型:{}".format(self.name, self.genre))
        return [self.name, self.genre]

add_name2.py 代码

class add_name2(object):
    def __init__(self, name, genre):
        self.name = name
        self.genre = genre

    def run(self):
        print("你叫{},你是一个{}".format(self.name, self.genre))
        return [self.genre, self.name]

3、执行动态加载
在Django项目运行中,可以直接上传代码到plugins目录中,然后调用initiator.py中的test()函数即可。
1)调用add_name

test("add_name", "add_name")

结果:
在这里插入图片描述
2)调用add_name2

test("add_name2", "add_name2")

结果:在这里插入图片描述

·
·
参考https://www.cnblogs.com/shhnwangjian/p/5955130.html

おすすめ

転載: blog.csdn.net/weixin_43796109/article/details/117072594