博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

tornado协程--gen.coroutine

Posted on 2017-12-24 11:08  马顿  阅读(820)  评论(0编辑  收藏  举报

一个使用gen.coroutine的实例:

1 @gen.coroutine
2 def asyncFunc():                      #自己定义的异步函数,由result_future代表
3     result_01 = yield async_step01()  #调用的其他异步过程,其返回的futrue,统一用setp_future代表
4     do_someting_with_result_01()
5     
6     result_02 = yield async_step02()  #调用的其他异步过程,其返回的futrue,统一用setp_future代表
7     do_someting_with_result_02()

去掉错误处理、对以前版本的兼容(yield_point)、修改了一些变量的名字后的coroutine源码:

 1 def coroutine(func):
 2     @functools.wraps(func)
 3     def wrapper(*args, **kwargs):
 4         result_future = TracebackFuture()   #为自定义的异步函数定义一个Future,代表该异步过程
 5         gen = func(*args, **kwargs)         #执行自定义的异步函数,获得genrator对象
 6         step_future = next(result)          #获得自定义的异步函数内,第一个异步函数的future
 7         Runner(gen, result_future, step_future) 
 8         return result_future
 9     return wrapper
10 
11 class Runner(object):
12     def __init__(self, gen, result_future, first_step_future):
13         self.gen = gen
14         self.result_future = result_future
15         if self.handle_step_future(first_step_future): #Future已结束则返回True,未结束则返回False
16             self.run()
17     
18     def run(self):
19         while True:
20             step_future = self.step_future
21             if not step_future.done():
22                 return
23             value = step_future.result()
24             
25             #获取自定义异步函数中,下一个异步过程的future
26             try:
27                 step_future = self.gen.send(value)
28             except (StopIteration, Return) as e:  
29                 #发生这两种异常说明整个自定义异步过程已经执行完毕,此时设置整个异步过程的future的值
30                 self.result_future.set_result(_value_from_stopiteration(e)) 
31             
32             #处理下一个异步过程的future
33             if not self.handle_step_future(step_future): 
34                 return
35     
36     def handle_step_future(self, step_future):
37         '''
38         如果该future已经结束:则返回True
39         如果该future还未结束:则将该future添加至ioloop中,并设置回掉函数为self.run,返回false
40         '''
41         self.step_future = step_future
42         if not self.step_future.done(): 
43             self.io_loop.add_future(self.step_future, lambda f: self.run())
44             return False
45         return True

coroutine的作用:

1、tornado中每个异步过程由一个Future来表示,coroutine会改变这种特性,让异步函数直接返回结果。这一点由第23、27行实现

2、coroutine可以让我们自定义的函数,在执行到异步调用时暂停,当该异步调用执行结束后,再重新启动我们的函数。这一点由Runner.handle_step_future()来实现。