一个使用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()来实现。