发布时间:2019-09-15 10:02:34编辑:auto阅读(2852)
Python中关于Timeout有另一种用起来更简便的方法,即使用装饰器。这种方式是使用sys模块的settrace等方法重构了python的threading类:
#!/usr/bin/python import threading import sys class KThread(threading.Thread): """Subclass of threading.Thread, with a kill() method.""" def __init__(self, *args, **kwargs): threading.Thread.__init__(self, *args, **kwargs) self.killed = False def start(self): """Start the thread.""" self.__run_backup = self.run """Force the Thread to install our trace.""" self.run = self.__run threading.Thread.start(self) def __run(self): """Hacked run function, which installs the trace.""" sys.settrace(self.globaltrace) self.__run_backup() self.run = self.__run_backup def globaltrace(self, frame, why, arg): if why == 'call': return self.localtrace else: return None def localtrace(self, frame, why, arg): if self.killed: if why == 'line': raise SystemExit() return self.localtrace def kill(self): self.killed = True
然后,构造一个timeout装饰器,这个装饰器利用上面重载的KThread实现超时限制:
def timeout(seconds): def timeout_decorator(func): def _new_func(oldfunc, result, oldfunc_args, oldfunc_kwargs): result.append(oldfunc(*oldfunc_args, **oldfunc_kwargs)) def _(*args, **kwargs): result = [] '''create new args for _new_funcbecause we want to get the func return val to result list ''' new_kwargs = { 'oldfunc': func, 'result': result, 'oldfunc_args': args, 'oldfunc_kwargs': kwargs } thd = KThread(target=_new_func, args=(), kwargs=new_kwargs) thd.start() thd.join(seconds) alive = thd.isAlive() '''kill the child thread''' thd.kill() if alive: alert_exce = u'function timeout for [%d s].' % seconds raise Timeout(alert_exce) else: return result[0] _.__name__ = func.__name__ _.__doc__ = func.__doc__ return _ return timeout_decorator
这种方法使用起来十分简单:只需要在需要超时控制的函数前面使用@timeout(sec)装饰器即可。
但是这种方法有比较明显的缺陷,因为其本质是使用将函数使用重载的线程来控制,一旦被添加装饰器的函数内部使用了线程或者子进程等复杂的结构,而这些线程和子进程其实是无法获得超时控制的,所以可能导致外层的超时控制无效。
上一篇: Python中的dir和help
下一篇: Windows下Python环境搭建图解
47844
46392
37284
34735
29313
25973
24916
19951
19545
18030
5792°
6414°
5929°
5962°
7064°
5911°
5945°
6438°
6404°
7778°