python的asyncio模组(二):异步程式设计基本概念

在说明asyncio的基本用法之前,先来说明一下异步程式设计的几项基本概念:

事件迴圈(event loop)事件(event)回调函数(callback)

先来思考一下为什么异步程式设计为什么要存在:

有多个任务需要同时执行

多个任务可以同时进行才符合一般人使用电脑的需求,假设我今天打开电脑,我想要一边听音乐一边看网页,播放音乐是一个任务,显示网页又是一个任务,若任务无法同时进行的话,难道要先把音乐放完才能看网页吗?

虽然现在CPU是多核心,但打开工作管理员会发现任务实在太多了,所以通常一核心的CPU要同时处理多件事情,那就只能让任务各种穿插执行了,让人脑感觉好像是同时进行一样,像下面这张图:

http://img2.58codes.com/2024/20107274SCvIXGO0Vk.jpg
来源网址:https://laike9m.com/blog/huan-zai-yi-huo-bing-fa-he-bing-xing,61/

io调度时间比起CPU执行指令的时间实在是太长了

从上一篇文章python的asyncio模组(一):异步执行的好处就能知道io时间比CPU执行时间要花费更久,所以为了不要让CPU去等待io而浪费时间,我们就可以趁这段时间去切换执行其他任务,比如说播放音乐,从本地端或是网路上读取音乐档就是需要调动io,这时就可以利用中间小段空闲时间去开启并显示网页,等到io调动时间结束,就可以重新执行原本任务了。

一、事件迴圈(Event loop)

既然异步程式可以在多个任务之间切换,那想必这个程式的架构里一定有一个任务的list,这样程式才知道有什么样的任务可以做切换,而这个任务的list以及中间切换的机制,就是由事件迴圈(Event loop)来处理。

二、事件(Event)与回调函数(Callback)

现在Event loop裏面有一个list,若程式有一些任务需要以异步的方式去执行,那就需要以"Event:Callback"的型式注册进我们Event loop的list裏面,之后Event loop以for迴圈的方式去察看list裏面的Event是否发生,若发生了就执行相对应的Callback,并注销这个Event的监听。

打个比方,我今天对Event loop注册了三个任务:

"Event_A:Callback_A""Event_B:Callback_B""Event_C:Callback_C"

然后Event loop会如以下的方式循环的对list里面的事件做监听:

http://img2.58codes.com/2024/20107274GdFfJAAMGR.png

假设正在监听的Event_B发生了,就会注销Event_B的监听(也就是把Event_B从list中移除),然后执行Callback_B,执行完后在继续监听剩下的事件。

http://img2.58codes.com/2024/20107274uhbfY2Zvg8.png

但上图的解释可能会出现一个疑问,里面的意思是执行完Callback_B之后才会继续监听,但假设在执行Callback_B这个任务的中途,出现了需要调动io的指令,不就应该要先放下Callback_B这个任务,去监听其他事件并执行其他任务吗?为什么要等到Callback_B执行完呢?

没错,异步程式设计应该要在遇到io读取的时候切换其他任务去执行,但上图确实是Event_loop的实作机制,所以如果你的Callback_B的内容像以下这样:

def Callback_B():    do_some_work1()    read_from_io_and_wait() # 读取io的指令,等到读取完成才能执行下一个指令    do_some_work2()    return

你的程式是没有办法中途去切换其他任务的,若要能够切换其他任务,应该要设计成以下型式:

def Callback_B():    do_some_work1()    read_from_io_and_not_wait() # 读取io的指令,不用等到读取完成就直接执行下一个指令    register_to_EventLoop("finish read from io",Callback_D)    returndef Callback_D():     # 等到Callback_B读取io的指令完成并被EventLoop监听到就执行    do_some_work2()    return

事实上如果Callback_B若要有遇到调动io指令就暂停执行的功能,那他应该要设计成遇到调动io指令,就多注册一个"Event_D:Callback_D"进去Event loop list,这个Event_D指的是"调动io完成",Callback_D的任务範围是完成调动io"后"所要执行的指令,而Callback_B的任务範围应该只有完成调动io"前"所要执行的指令。

http://img2.58codes.com/2024/20107274l3cqMWDzux.png

下一篇教学:
python的asyncio模组(三):建立Event Loop和定义协程

参考资料:
Event loop的实作细节
http://lotabout.me/2017/understand-python-asyncio/


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章