搞定在线编译,那看看调用的方式呢?
调用主要是通过上面所说 @{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: 关键字执行的结果
"""
...
搞定!