python的asyncio模组(四):Event loop常用API

先来複习一下前面的教学:

上上一篇的python的asyncio模组(二):异步程式设计基本概念,我们学到异步程式设计的3个基本概念:

事件迴圈(Event loop)事件(Event)回调函数(Callback)

上一篇的python的asyncio模组(三):建立Event Loop和定义协程,我们得知如何定义asyncio程式的两个最基本的要素:

事件迴圈(Event loop)协程(Coroutine)

其中Coroutine能中途暂停和恢复运作的特性可以很好的实现异步程式设计中的Event与Callback两个概念,又能避免以前残害javascript开发者许久的callback hell。

因为当我们要在一个Coroutine里中途监听某一个Event发生后再执行后续行为时,只需要用await关键字来等待某个Event发生:

def a_coroutine():   # do something...    ...        await listen_event_happend()        # do something after event happend...    ...

而不需要明确定义需要监听的Event以及对应的Callback,并注册到Event loop里,这就很可能会导致callback hell的状况:

def a_coroutine():    # do something...    ...        def do_something_after_event_happend():        # do something after event happend...        ...    register_to_event_loop(listen_event_happend, do_something_after_event_happend)

若上面的例子还闻不出callback hell的味道,可以请读者想想看以下的例子,要如何改成需要明确定义Event和Callback的写法:

def a_coroutine():   # do something...    ...        await listen_event1_happend()    # do something after event1 happend...    ...        await listen_event2_happend()    # do something after event2 happend...    ...        await listen_event3_happend()    # do something after event3 happend...    ...

因为Coroutine和一般的函数特性有一些本质上的差异,他可以中途暂停等待某个事件发生,所以我们对于一个Coroutine的业务操作,会比一般的函数还要更多,所以asyncio所衍生出来的基本语法就看起来非常的多样且複杂。

但若掌握了一些基本的方向,对于常用的基本语法,我们还是能逐步的了解这些语法为何被发明出来且如何被使用。

我们必须先了解,当我们定义了一个Coroutine function后,一直到这个function被Event loop执行的过程中,这个function会经历几次的对象转换:

Coroutine function --> Coroutine object --> Task

我们可以从以下例子了解到其中的对象转换过程:

# python3.5# ubuntu 16.04import asyncioasync def func():    print('func start')    await asyncio.sleep(1)    print('func end')loop = asyncio.get_event_loop() # 建立一个Event loopprint(func) # 原本是一个coroutine functionobj=func()print(obj) # 执行之后回传一个coroutine objecttask = asyncio.ensure_future(obj)print(task) # 经过ensure_future包装成一个Future对象(也可以说是一个Task对象,两者的差别下一篇教学会说明)loop.run_until_complete(task) # 把task丢入Event loop执行,并在task结束时结束Event loop'''Output:<function func at 0x7f28e365aa70><coroutine object func at 0x7f28e365a9e0><Task pending coro=<func() running at test.py:3>>func startfunc end'''

当我们执行coroutine function之后,并不会真得到执行的结果,事实上function也没有执行,而是得到一个协程对象(coroutine object)。

然后ensure_future会把coroutine object封装程一个task对象,在python的asyncio模组(三):建立Event Loop和定义协程就有提到过,这个对象可以储存任务执行时的状态与环境,所以coroutine才能暂停与恢复运行。

2020/05/24更新
coroutine object本身就能储存任务执行时的状态与环境,而task对象是作为Event loop和coroutine的沟通介面

然后这个Task对象才能真正丢入Event loop下去执行,但就上面的程式来说,我们也可以把coroutine object作为参数丢进loop.run_until_complete,只是在run_until_complete里也还是会把coroutine object转成Task对象再去执行。

接下来我们来讲一下和Event loop有关的一些常用基本语法:

loop.run_until_complete(future)

这个函数接收一个Task对象,并指定这个Event loop若执行完这个被传入Task就会停止,不管loop裏面还有没有其他的Task正在执行当中或是等待执行。

而如同上面所说,这个参数也可以传入coroutine object,只是在放入Event loop执行前,这个coroutine object会先被转成Task对象。

loop.run_forever()

顾名思义,这个函数会让一个loop无止境的运行下去,就算当中所有Task已经被执行完毕只剩下空的loop在运转,除非在程式中呼叫loop.stop()才能够停止这个Event loop。

loop.create_task(coro)

这个函数会接收一个coroutine object,并包装成一个Task对象,同时把这个Task注册到这个Event loop中等待执行。

而当loop.run_until_complete或loop.run_forever被呼叫时,这些被注册进去的Task才会被执行。

loop.create_future()

这个函数不接收任何的参数,然后会回传一个空的Future对象,并注册到Event loop裏面等待执行。

目前可以视Future对象和Task对象为一样的东西,两者定义上的差别下一次会说明。

loop.is_running()

判定一个Event loop是否还在运作。

loop.is_closed()

判定一个Event loop是否已经被close掉。

loop.stop()

stop一个Event loop。

loop.close()

close掉一个Event loop。

下一篇教学:
python的asyncio模组(五):Future对象与Task对象

参考资料:
https://www.jianshu.com/p/b5e347b3a17c
https://www.dongwm.com/post/understand-asyncio-2/
https://juejin.im/post/5c2f12ce6fb9a04a006f2659


关于作者: 网站小编

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

热门文章