集成python脚本作为平台脚本,当用户脚本执行超时如何强制结束运行?
当将python脚本作为一个插件集成一个平台之中时,后台无法判断用户提交的python代码块中是否存在死循环情况,当python脚本块执行达到超时条件后若脚本还未正常退出则需要强制结束,此种情况有两个方法实现:
1. 通过mulitprocess将用户代码作为一个进程单独运行,当代码块超时则强制结束子进程(推荐)
2. 通过设置threading.settrace方法实现, 将用户脚本块的执行入口方法通过线程启动,然后等待线程超时后抛出异常结束线程,该方法影响整体性格,毕竟settrace的初衷是为了实现IDE的调试功能,但是有时候第一种方法受到限制无法使用,而python线程又没有强制结束的方法,因此可以作为一个解决方案,以下为示例代码:
import time
import threading
def greetings():
""" dead loop testing """ print('start greetings') try: while True: time.sleep(1) print(f'{datetime.datetime.now()}: thread id ={threading.current_thread().ident} ') except Exception as e: print(e) print('finish')
def thead_state_trace(frame, event, arg):
global is_thread_killed
if is_thread_killed and 'line' == event:
raise Exception(f'thread[{threading.current_thread().ident}] killed!!!')
return thead_state_trace
is_thread_killed = False
def main(timeout):
print(f'1. start thread {threading.current_thread().ident} timeout={timeout} ...')
threading.settrace(thead_state_trace)
t = threading.Thread(target=greetings, name='greetingsThread', daemon=True)
t.start()
print(f'2. start thread: {t.name}')
t.join(timeout)
if t.is_alive():
global is_thread_killed
is_thread_killed = True
print(f'3. thread: {t.name} daemon={t.daemon} timeout!!!')
else:
print(f'3. thread: {t.name} ok!')