【笔记】asyncio理解入门

python运行的单进程单线程的程序,并不能提升运算速度,比较适合需要处理等到的任务,如网络通信,

asyncio的核心是一个event loop,就像一个大脑,面向很多task,然后决定执行哪个task,同时执行的任务只能有一个,不存在系统级的上下文切换,它需要每一个task主动告诉event loop:我这边结束了,可以让别的task开始,不存在竞争冒险的问题,可以明确知道每一个任务什么时候停止运算了。

首先要理解coroutine和task:

Coroutine function:上图中的async def main就是,python里面所有async开头的东西都叫Coroutine function,定义了一个Coroutine的过程,Coroutine function调用的时候返回Coroutine object。执行到core = main()的时候并不会执行程序,只会返回Coroutine object。

Coroutine object。

如何运行Coroutine function里面的代码呢?

        第一,进入async模式,进入even loop

Asyncio.run(),参数为coroutine会建立even loop,把Coroutine 变成这个even loop里面的第一个task,event loop 建立之后就会去找哪个task可以执行。

Event loop的核心是它有很多很多task,然后它决定哪个task要运行,所有很重要的一件事情是当已经处于async模式下的时候,如何增加task。

        第二,把Coroutine 变成task,让它可以排队执行的方法:

(asyncio.sleep返回的东西也是一个coroutine)

        方法1:await,await coroutine 的时候,会发生以下事情:

  1. 这个coroutine被包装成一个task,并且被告诉event loop这里有个新的task;
  2. 控制权交还。它会告诉event loop 现在这个task需要等到say_after task 完成之后我才能继续,建立了这种依赖关系;
  3. 会yeild出去,会告诉event loop,我这个task现在干不了,先让别的task去干。

        综上所述,这段代码的过程为:asyncio.run()把main()返回的coroutine变成task,event loop里面就这一个task,然后执行到await say_after(1, ’hello’),这个coroutine被包装成一个task,并且被告诉event loop这里有个新的task;它会告诉event loop 现在这个main task需要等到say_after task 完成之后我才能继续,say_after task里面类似。这里需要3秒完成整个main()程序。

问题:为啥等待1s和等待2s不能一起等呢?

这是协程的意义。

        create_task()可以解决这个问题,其参数为coroutine,create_task()会把传进来的coroutine变成一个task,并且把task注册到event loop里面,也就是说它分担了await coroutine 的一部分功能。他把coroutine包装成一个task,并且告诉event loop 说这个task已经可以开始执行了。但是现在event loop并没有办法执行这个task,因为控制权还在main的手里这个时候main趁着自己有控制权,它就做了第二个task2,也是告诉main这里还有一个新的task,say_task2也可以运行了,在这之后开始await task1,await task2,告诉event loop:我需要这个task完成。这里只需要2秒完成整个main()程序。Await task1的时候event loop里面实际有3个task,task1和event loop 说完“我要等1s才能完成”后,event loop发现task2还可以执行,于是执行task2,所以两个task可以同时等待。(task可以放权,coroutine不能放权。)

        如果有很多task,可以用gather()函数,它的参数是若干个coroutine或者task,甚至是future。它会返回future,这个future也可以用await。这里ret返回是一个list,就是每个task执行完后的返回值。

        总结:如果代码里面没有等待这件事的话,协程对这个代码是没有帮助的,分清coroutine和task,coroutine只有被变成task才开始被执行,要能知道coroutine什么时候被隐式地变成了task。最后拿到coroutine的返回值需要用await,一个变量=await coroutine object。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值