Tornado 异步怎么写的?

2018-12-02 12:22:59 +08:00
 aoscici2000

比如说要等某个耗时操作的结果, 该怎么写?

网上看了半天例子, 照着做了做, 貌似行不通

class AsyncTaskHandler(tornado.web.RequestHandler):

@tornado.web.asynchronous
@tornado.gen.coroutine
def get(self, *args, **kwargs):
    resp = yield tornado.gen.Task(self.do_something)
    self.finish(resp)

@tornado.gen.coroutine
def do_something(self, *args, **kwargs):
    time.sleep(10)
    return {'message': 'OKOK'}
7655 次点击
所在节点    Tornado
11 条回复
mywaiting
2018-12-02 13:23:57 +08:00
Tornado 的 gen.corountine 里面如果要 sleep 必须用这个 tornado.gen.sleep()

多点看看官方的文档,比网上的例子靠谱得多。网上很多的例子,很可能写例子本身的人就不懂 Tornadp

文档链接 http://www.tornadoweb.org/en/stable/gen.html#tornado.gen.sleep
zhengxiaowai
2018-12-02 18:13:04 +08:00
aoscici2000
2018-12-02 19:47:17 +08:00
@zhengxiaowai 这篇好像也看过, 例子照做过, 但只要把他那个 gen.sleep() 改成自己要做的事情, 依然堵塞,,,
Vegetable
2018-12-02 23:03:19 +08:00
你自己要做的事情,必须也是 non-blocking 的.
就比如这个 time.sleep,他阻塞了整个进程.而 gen.sleep 是非阻塞的,所以不会阻塞.
所以数据库操作要用专门的异步驱动,网络操作要用 tornado 自己的异步 client 等等.
aoscici2000
2018-12-03 01:40:03 +08:00
@Vegetable 那假设我要耗时取得某些数据返回, 直接开个新线程去处理, 就算异步了? 例如:

def get_db(self):
data = requests.get('xxx.com')
self.render('t.html', data=data)

class GetDBHandler(MyHandler):
@tornado.web.asynchronous
def get(self):
t = threading.Thread(target=get_db, args=(self,))
t.start()
Vegetable
2018-12-03 09:30:30 +08:00
@aoscici2000
requests 是一个同步的客户端,你这个例子可以用 aiohttp 或者 tornado 的 AsyncHTTPClient 这种非阻塞的 HTTP 工具,IO 就不会阻塞了.耗时操作必须写成异步的,异步框架才有意义,不然还是会阻塞事件循环.
Aresn
2018-12-03 09:32:44 +08:00
用 Celery ?
zhengxiaowai
2018-12-03 10:30:54 +08:00
@aoscici2000 仔细看构成异步的条件,简单来说只要 handle 中有一个耗时的步骤不是异步的,那么这个 handle 就不是异步的了。

最简单的方法是使用 threadpoolexecutor
aoscici2000
2018-12-04 12:52:16 +08:00
@Aresn 新手, 还没接触这东西, 暂时也没时间哎
singed
2019-01-03 20:24:19 +08:00
import tornado.ioloop
import tornado.web
from tornado import gen
from tornado.httpclient import AsyncHTTPClient


class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("hello world")


class ASyncHandler(tornado.web.RequestHandler):

@gen.coroutine
def get(self):
print("11111111111")
self.write("hello world -------")


class A2SyncHandler(tornado.web.RequestHandler):
@gen.coroutine
def get(self):
http_client = AsyncHTTPClient()
print("777777777777")
# http_client.fetch 会进入阻塞的方法, 切换协程
# response = yield http_client.fetch("https://asia.playstation.com/hk")
# res = response.body
# 放开下面一行注释, /async 必须等这里跑完才会跑, 也会有被阻塞的感觉
res = str(jies(600)) # 不会进入阻塞的方法, 线程可能一直被这个函数占用了,
# yield gen.sleep(10) 主动让出 10 秒执行权, 10 秒后回到这里执行
print("888888888888")
self.write(res)


application = tornado.web.Application([
(r"/", MainHandler),
(r"/async", ASyncHandler),
(r"/async2", A2SyncHandler)],
)


def jies(n):
for i in range(10**5):
x = 1
return n*jies(n-1) if n != 1 else 1


if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
singed
2019-01-03 20:25:42 +08:00
楼主, 怎么贴有颜色的代码?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/513504

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX