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


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

    调用主要是通过上面所说 @{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: 关键字执行的结果
        """
        ...
    

    搞定!

  • 相关阅读:
    window.open跨页面传输
    history对象
    类vr特效的360度全景
    移动端图片滑动
    图片拼图
    20180808 考试记录
    [jzoj 5770]【2018提高组模拟A组8.6】可爱精灵宝贝 (区间dp)
    20180806 考试记录
    [luogu2319 HNOI2006] 超级英雄 (匈牙利算法)
    [luogu2679] 子串 (多维dp)
  • 原文地址:https://www.cnblogs.com/guanhuohuo/p/12533574.html
Copyright © 2020-2023  润新知