我怎样才能取消挂asyncronous任务龙卷风,一个超时? [英] How can I cancel a hanging asyncronous task in tornado, with a timeout?
问题描述
我的设置是蟒蛇龙卷风服务器,该服务器异步处理与的ThreadPoolExecutor
任务。在某些情况下,任务可能变成无限循环。随着 with_timeout
装饰,我已成功地捕捉到超时异常和错误的结果返回给客户端。问题是,该任务仍然在后台运行。它是如何可能从运行中停止任务的的ThreadPoolExecutor
?或者是有可能取消未来
?
这里是code能重现问题。运行code。与龙卷风4和concurrent.futures库和去的http://本地主机:8888 /测试
从tornado.concurrent进口run_on_executor
从tornado.gen进口with_timeout
从tornado.ioloop进口IOLoop
进口tornado.web
从龙卷风进口根
从concurrent.futures进口的ThreadPoolExecutor
进口日期时间
MAX_WAIT_SECONDS = 10类MainHandler(tornado.web.RequestHandler):
遗嘱执行人=的ThreadPoolExecutor(2) @run_on_executor
高清test_func(个体经营):
...
#infinite循环可能会在这里
... @ tornado.gen.coroutine
DEF得到(个体经营):
未来= self.test_func()
尝试:
result_search_struct =产量with_timeout(datetime.timedelta(秒= MAX_WAIT_SECONDS),未来)
self.write({'状态':0})
self.finish()
除例外,E:
#如何在这里取消任务,如果它是超时
future.cancel()#< - 不工作
self.write({状态:100})
self.finish()应用= tornado.web.Application([
(R/测试,MainHandler)
])
application.listen(8888)
IOLoop.instance()。开始()
未来
实例本身不能被取消,他们只能被取消如果他们处于挂起状态。这说明在文档:
取消()
尝试取消呼叫。如果当前正在执行的呼叫,无法取消,则该方法将返回
假
,
否则通话将被取消,该方法将返回真
。
块引用>所以,放弃你在后台运行的方法,唯一的办法就是实际的逻辑插入到你的潜在的无限循环,以便它可以当你告诉它被中止。随着你的榜样,你可以使用
threading.Event
:类MainHandler(tornado.web.RequestHandler):
遗嘱执行人=的ThreadPoolExecutor(2) @run_on_executor
高清test_func(个体经营,事件):
I = 0
同时不event.is_set():
我打印
I = I + 1 @ tornado.gen.coroutine
DEF得到(个体经营):
事件= threading.Event()
未来= self.test_func(事件)
尝试:
result_search_struct =产量with_timeout(datetime.timedelta(秒= MAX_WAIT_SECONDS),未来)
self.write({'状态':0})
self.finish()
除例外,E:
future.cancel()#可能不起作用,这取决于执行者的繁忙程度
event.set()
self.write({状态:100})
self.finish()应用= tornado.web.Application([
(R/测试,MainHandler)
])My setup is python tornado server, which asynchronously processes tasks with a
ThreadPoolExecutor
. In some conditions, the task might turn into infinite loop. With thewith_timeout
decorator, I have managed to catch the timeout exception and return an error result to the client. The problem is that the task is still running in the background. How it is possible to stop the task from running in theThreadPoolExecutor
? Or is it possible to cancel theFuture
? Here is the code that reproduces the problem. Run the code with tornado 4 and concurrent.futures libraries and go to http://localhost:8888/testfrom tornado.concurrent import run_on_executor from tornado.gen import with_timeout from tornado.ioloop import IOLoop import tornado.web from tornado import gen from concurrent.futures import ThreadPoolExecutor import datetime MAX_WAIT_SECONDS = 10 class MainHandler(tornado.web.RequestHandler): executor = ThreadPoolExecutor(2) @run_on_executor def test_func(self): ... #infinite loop might be here ... @tornado.gen.coroutine def get(self): future = self.test_func() try: result_search_struct = yield with_timeout(datetime.timedelta(seconds=MAX_WAIT_SECONDS), future ) self.write({'status' : 0}) self.finish() except Exception, e: #how to cancel the task here if it was timeout future.cancel() # <-- Does not work self.write({'status' : 100}) self.finish() application = tornado.web.Application([ (r"/test", MainHandler), ]) application.listen(8888) IOLoop.instance().start()
解决方案
Future
instances themselves can't be cancelled once they're actually executing, they can only be cancelled if they're in a pending state. This is noted in the docs:cancel()
Attempt to cancel the call. If the call is currently being executed and cannot be cancelled then the method will return
False
, otherwise the call will be cancelled and the method will returnTrue
.So, the only way to abort the method you're running in the background is to actually insert logic into your potentially infinite loop so that it can be aborted when you tell it to. With your example, you could use a
threading.Event
:class MainHandler(tornado.web.RequestHandler): executor = ThreadPoolExecutor(2) @run_on_executor def test_func(self, event): i = 0 while not event.is_set(): print i i = i + 1 @tornado.gen.coroutine def get(self): event = threading.Event() future = self.test_func(event) try: result_search_struct = yield with_timeout(datetime.timedelta(seconds=MAX_WAIT_SECONDS), future ) self.write({'status' : 0}) self.finish() except Exception, e: future.cancel() # Might not work, depending on how busy the Executor is event.set() self.write({'status' : 100}) self.finish() application = tornado.web.Application([ (r"/test", MainHandler), ])
这篇关于我怎样才能取消挂asyncronous任务龙卷风,一个超时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!