从头造轮子:python3 asyncio之 gather (3) (4)

从队列中取出数据,此时_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 = None

3.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 = None

result = 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 ret

helloworld终于也执行完了,返回了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 ...'] 五、流程总结

从头造轮子:python3 asyncio之 gather (3)

六、小结

● 终于结束了,这是一个非常长的小节了,但是我感觉很多细节还是没有说到,大家有问题请及时留言探讨
● _GatheringFuture一个非常重要的对象,它不但追踪了hello() world()的执行状态,唤醒helloworld(),并且将返回值传递给helloworld
● await async yield对流程的控制需要特别关注
● 本文中的代码,参考了python 3.7.7中asyncio的源代码,裁剪而来
● 本文中代码:代码

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzfgdz.html