文章目录

Tornado中,要使一个任务,我们经常需要用Tornado自己的异步模块,或者适配Tornado的第三方异步模块。

但很多情况下我们需要的功能模块可能没有适配Tornado的异步模型,然后我们自己又不可能造一个轮子。
这个时候,我们就可以使用Tornado自带的通过线程来将同步方法异步化。

虽然Tornado是单线程异步的Web框架,但是它也提供了使用线程来将同步任务异步化的装饰器。

tornado.concurrent这个模块中有一个装饰器run_on_executor,使用它装饰在请求处理器的方法上,来使用线程将该同步任务异步话。

下面给出示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/usr/bin/env python3
# coding: utf-8

import time
import concurrent.futures

import tornado.web
import tornado.concurrent
import tornado.ioloop
import tornado.gen


class AsyncHandler(tornado.web.RequestHandler):

# 要求请求处理器有一个`executor`属性表示异步执行器
# 创建一个size为4的线程池执行器
executor = concurrent.futures.ThreadPoolExecutor(4)

@tornado.gen.coroutine
def get(self):
futures = [self.sleep(1) for i in range(8)]
results = yield futures
print(results)

# 同步任务通过执行器异步化
@tornado.concurrent.run_on_executor
def sleep(self, sec):
time.sleep(sec)
return time.time()

pass


if __name__ == "__main__":
app = tornado.web.Application([(r"/", AsyncHandler)])
app.listen(8000)
tornado.ioloop.IOLoop.current().start()

启动Web服务后,访问/

1
2
jzqt@Dreamer:~$ curl localhost:8000/
[1467202920.2401285, 1467202920.240263, 1467202920.2402115, 1467202920.2403257, 1467202921.240244, 1467202921.2412646, 1467202921.2413185, 1467202921.241381]

可以看出,同步任务确实是异步化了。上面的用例是通过线程池来异步的,更多的使用方法就不多讲了,可以研究官方文档等。

注意:计算密集型任务使用线程优化作用不大,因为Python有GIL大家懂得。

文章目录