def settimeout(timeout=15):
"""
超过函数执行时间raise TimeoutError
:param args:
:param kwargs:
:return:
"""
def _(func):
def handler():
raise TimeoutError("function running timeout")
@wraps(func)
def wrap(*args, **kwargs):
if platform == "linux2":
signal.signal(signal.SIGALRM, handler)
signal.alarm(timeout)
res = func(*args, **kwargs)
signal.alarm(0)
elif platform == "win32":
try:
t = mythread(target=func, args=args, kwargs=kwargs)
t.start()
t.join(timeout)
if t.getResult() is None:
stop_thread(t)
handler()
except Exception as e:
raise e
else:
res = t.getResult()
return res
return wrap
return _
class mythread(threading.Thread):
def __init__(self, group=None, target=None, name=None, args=(), kwargs=None, *, daemon=None):
super(mythread, self).__init__(group=None, target=None, name=None,args=(), kwargs=None, daemon=None)
self.target = target
self.args = args
self.kwargs = kwargs
self.result = None
def run(self):
self.result = self.target(*self.args, **self.kwargs)
def getResult(self):
return self.result
def _async_raise(tid, exctype):
"""raises the exception, performs cleanup if needed"""
tid = ctypes.c_long(tid)
if not inspect.isclass(exctype):
exctype = type(exctype)
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
if res == 0:
raise ValueError("invalid thread id")
elif res != 1:
# """if it returns a number greater than one, you're in trouble,
# and you should call it again with exc=NULL to revert the effect"""
ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
raise RuntimeError("runtime error")
def stop_thread(thread):
_async_raise(thread.ident, TimeoutError)