在Tornado中运行阻止代码
我有一个龙卷风应用程序,我想用一个阻塞库来完成一些事情。 如果无法以异步方式重写库,那么在龙卷风中执行它的方式是什么?
例如,我希望能够在请求处理程序中放置一个@asynchronous
装饰器,并在其中启动一个长时间运行的函数,该函数一旦完成就会返回响应。 我不能只是回拨。 最简单的例子当然是什么才是正确的方式睡10秒,而不会阻止龙卷风的唯一线程?
看起来我想要的仅仅是创建一个新的线程/进程,并且回调龙卷风的实际行为需要使用IOLoop.instance().add_callback
更多信息请点击这里
所接受的答案涉及的代码可在SO上找到。
另一种方法在这里的博客文章中详细介绍,以及完整的工作要点。 以下是来自要点的代码的重新发布:
from concurrent.futures import ThreadPoolExecutor
from functools import partial, wraps
import time
import tornado.ioloop
import tornado.web
EXECUTOR = ThreadPoolExecutor(max_workers=4)
def unblock(f):
@tornado.web.asynchronous
@wraps(f)
def wrapper(*args, **kwargs):
self = args[0]
def callback(future):
self.write(future.result())
self.finish()
EXECUTOR.submit(
partial(f, *args, **kwargs)
).add_done_callback(
lambda future: tornado.ioloop.IOLoop.instance().add_callback(
partial(callback, future)))
return wrapper
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world %s" % time.time())
class SleepHandler(tornado.web.RequestHandler):
@unblock
def get(self, n):
time.sleep(float(n))
return "Awake! %s" % time.time()
class SleepAsyncHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
def get(self, n):
def callback(future):
self.write(future.result())
self.finish()
EXECUTOR.submit(
partial(self.get_, n)
).add_done_callback(
lambda future: tornado.ioloop.IOLoop.instance().add_callback(
partial(callback, future)))
def get_(self, n):
time.sleep(float(n))
return "Awake! %s" % time.time()
application = tornado.web.Application([
(r"/", MainHandler),
(r"/sleep/(d+)", SleepHandler),
(r"/sleep_async/(d+)", SleepAsyncHandler),
])
if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
下面试试这个例子。
import tornado.ioloop
import tornado.web
import time
class MainHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
def get(self, request):
if request is None:
self.application.go = False
self.write("Waiting for GET @ http://localhost:8888/go...<br>")
self.flush()
self._do_wait()
else:
self.application.go = True
self.finish('Thanks!')
def _do_wait(self, timeout_trys=10):
if self.application.go:
self.write('Finish')
self.finish()
else:
self.write("Sleeping 2 second, timeout_trys=%s<br>" % timeout_trys)
self.flush()
tornado.ioloop.IOLoop.instance().add_timeout(time.time() + 2,
lambda: self._do_wait(timeout_trys-1))
application = tornado.web.Application([
(r"/(w+)?", MainHandler),
])
if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
链接地址: http://www.djcxy.com/p/27847.html