【代码运行服务】调用执行

搞定在线编译,那看看调用的方式呢?

调用主要是通过上面所说 @{fun_name(param1, param2)}@ 这样的方式调用编写好的代码,并得到return的值
通过subprocess.check_output的方式发现暂时无法实现我们想要的功能,是否可以通过eval或者其他方式执行呢?
发现其实是可以的

def call_func(fun_call, code):
    """
    调用执行关键字
    :param fun_call: 关键字调用字符串(关键字+参数)
    :param code: 代码文件
    :return: 关键字执行的结果
    """
    try:
        # 处理字符串,获取关键字名称
        kw_fun_name = fun_call.split('(')[0]
        # 生成代码执行的文件
        mk_code = MkCode(kw_fun_name,code)
        # 加载路径
        sys.path.append(mk_code.temp_path)
        # 动态加载文件
        module_name = kw_fun_name
        imp_module = __import__(module_name)
        # 文件调用,勿删
        obj = imp_module
        _call_fun_ = "obj."+str(fun_call)
        # 执行关键字函数,并返回结果
        return eval(_call_fun_)
    except Exception as e:
        traceback.print_exc()
        return str(e)

那在线编译可以实现timeout的方式,调用的时候也必须有超时时间的设置,如何设置方法执行的超时时间呢?

可以通过thread + time
原理:将要调用的功能函数放入子线程,通过设定子线程的阻塞时间,超时则主线程并不会等待子线程的执行。主线程退出,子线程就不存在了。
核心就是在程序中添加 join()方法,用于等待线程结束。join()的作用是,在子线程完成运行之前,这个子线程的父线程将会被一直阻塞

# coding=utf-8
import threading
import time


def myFunc():
    time.sleep(4)
    print("myFunc执行了")


if __name__ == '__main__':
    t = threading.Thread(target=myFunc)
    t.setDaemon(True)
    t.start()

    t.join(2)
    print("it's over")

执行结果:
  it's over
可以看出,当主线程执行到2秒时候,结束退出。子线程还没有结束,没有执行完及被强制退出

故可以参照这样的方式实现

import threading

class MyThread(threading.Thread):

    def __init__(self, target, args=()):
        """
        why: 因为threading类没有返回值,因此在此处重新定义MyThread类,使线程拥有返回值
        此方法来源 https://www.cnblogs.com/hujq1029/p/7219163.html?utm_source=itdadao&utm_medium=referral
        """
        super(MyThread, self).__init__()
        self.func = target
        self.args = args

    def run(self):
        # 接受返回值
        self.result = self.func(*self.args)

    def get_result(self):
        # 线程不结束,返回值为None
        try:
            return self.result
        except Exception:
            return None


def limit_decor(limit_time):
    """
    为了限制真实请求时间或函数执行时间的装饰器
    :param limit_time: 设置最大允许执行时长,单位:秒
    :return: 未超时返回被装饰函数返回值,超时则返回 None
    """

    def functions(func):
        # 执行操作
        def run(*params):
            thre_func = MyThread(target=func, args=params)
            # 主线程结束(超出时长),则线程方法结束
            thre_func.setDaemon(True)
            thre_func.start()
            # 定义函数执行超时时间
            thre_func.join(limit_time)
            # 最终返回值(不论线程是否已结束)
            if thre_func.get_result():
                return thre_func.get_result()
            else:
                return"关键字函数执行超时"
        return run
    return functions

将函数执行时间控制器定义成装饰器

@limit_decor(10)
def call_func(fun_call, code):
    """
    调用执行关键字
    :param fun_call: 关键字调用字符串(关键字+参数)
    :param code: 代码文件
    :return: 关键字执行的结果
    """
    ...

搞定!

原文地址:https://www.cnblogs.com/guanhuohuo/p/12533574.html