从队列中取出数据,此时_ready队列有两个任务,hello() world(),在gather的for循环时添加的
async def hello(): print('enter hello ...') return 'return hello ...' async def world(): print('enter world ...') return 'return world ...'由于hello() world()没有await调用其他异步任务,所以他们的执行比较简单,分别一次task.__step就结束了,到达set_result()处
set_result()将回调函数放入_ready队列,等待下次循环执行
3.5)第三次循环run_forever --> run_once
我们来看下回调函数
def _done_callback(fut): nonlocal nfinished nfinished += 1 if nfinished == nfuts: results = [] for fut in children: res = fut.result() results.append(res) outer.set_result(results)没错,这是本文的第二个核心点,我们来仔细分析一下
这段代码最主要的逻辑,其实就是,只有当所有的子任务执行完之后,才会启动父任务的回调函数,本文中只有hello() world()都执行完之后if nfinished == nfuts: ,才会启动父任务_GatheringFuture的回调outer.set_result(results)
results.append(res)将子任务的结果取出来,放进父任务的results里面
子任务执行完成,终于到了唤醒父任务的时候了task.__wakeup
def __wakeup(self, future): try: future.result() except Exception as exc: raise exc else: self.__step() self = None3.6)第四次循环run_forever --> run_once
future.result()从_GatheringFuture取出结果,然后进入task.__step
def __step(self, exc=None): coro = self._coro try: if exc is None: result = coro.send(None) else: result = coro.throw(exc) except StopIteration as exc: super().set_result(exc.value) else: blocking = getattr(result, '_asyncio_future_blocking', None) if blocking: result._asyncio_future_blocking = False result.add_done_callback(self.__wakeup, result) finally: self = Noneresult = coro.send(None)其实就是helloworld() --> send又要跳回到当初yield的地方,那就是Future.__await__
def __await__(self): if self._state == _PENDING: self._asyncio_future_blocking = True yield self return self.result()return self.result()终于返回到helloworld()函数里面去了
async def helloworld(): print('enter helloworld') ret = await wilsonasyncio.gather(hello(), world()) print('exit helloworld') return rethelloworld终于也执行完了,返回了ret
3.7)第五次循环run_forever --> run_once
循环结束
回到run
3.8)回到主函数,获取返回值
if __name__ == "__main__": ret = wilsonasyncio.run(helloworld()) print(ret)3.9)执行结果
▶ python3 main.py enter helloworld enter hello ... enter world ... exit helloworld ['return hello ...', 'return world ...'] 五、流程总结 六、小结● 终于结束了,这是一个非常长的小节了,但是我感觉很多细节还是没有说到,大家有问题请及时留言探讨
● _GatheringFuture一个非常重要的对象,它不但追踪了hello() world()的执行状态,唤醒helloworld(),并且将返回值传递给helloworld
● await async yield对流程的控制需要特别关注
● 本文中的代码,参考了python 3.7.7中asyncio的源代码,裁剪而来
● 本文中代码:代码