python的asyncio模组(三):建立Event Loop和定义协程

在上一篇python的asyncio模组(二):异步程式设计基本概念讲解完异步程式设计的基本概念之后,就可以进入正式的主题了:

定义Event Loop
import asyncioloop = asyncio.get_event_loop() #建立一个Event Loop# 以下为基本的使用方法## loop.run_until_complete(coroutine)# coroutine是协程的意思,但其意义在下面会介绍,目前只要把他理解成一个任务就行了# 这个函数顾名思义,就是让注册参数里的任务并执行,等到任务完成就关闭Event Loop## loop.run_forever()# 这个函数一执行,Event Loop就会永远执行不会被关闭,除非在程式中出现loop.stop()就停止#
定义协程(coroutin)

先解释协程的意义,协程可以看做是"能在中途中断、中途返回值给其他协程、中途恢复、中途传入参数的函数",和一般的函数只能在起始传入参数,不能中断,而且最后返回值给父函数之后就结束的概念不一样。

定义协程很简单,只要在定义函数时再前面加入"async"这个关键字就行了:

# python3.5# ubuntu 16.04import asyncioloop = asyncio.get_event_loop() #建立一个Event Loopasync def example(): # 定义一个协程    print("Start example coroutine.")    # do some process...    print("Finish example coroutine.")loop.run_until_complete(example())# 把example这个coroutine注册到事件循环里# 被注册进去的事件的定义是loop一启动就直接触发的,所以example里面的任务内容会马上执行# output:# Start example coroutine.# Finish example coroutine.

但以上的例子无法体会到为何协程可以"中途中断、中途恢复执行",下个例子我们可以在协程里加入asyncio.sleep函数让他中途暂停执行,并将执行权转到其他的函数,之后在恢复执行:

# python3.5# ubuntu 16.04import asyncioloop = asyncio.get_event_loop() #建立一个Event Loopasync def example1(): # 定义一个中间会被中断的协程    print("Start example1 coroutin.")    await asyncio.sleep(1) # 中断协程一秒    print("Finish example1 coroutin.")async def example2(): # 定义一个协程    print("Start example2 coroutin.")    # do some process...    print("Finish example2 coroutin.")tasks = [ # 建立一个任务列表    asyncio.ensure_future(example1()),    asyncio.ensure_future(example2()),]loop.run_until_complete(asyncio.wait(tasks))# 把example1, example2这两个coroutin注册到事件循环里# loop启动,先执行example1,中途暂停example1之后切换到example2,最后再切回example1# output:# Start example1 coroutin.# Start example2 coroutin.# Finish example2 coroutin.# Finish example1 coroutin.

从output资讯可以看出example1是有被中断执行的但上面的範例多了几个需要解释的东西:

asyncio.ensure_future(example1())
这函数把协程对象封装成一个task对象,这个对象可以储存任务执行时的状态与环境,通常大家会说这对象储存了任务的"上下文"(context),因为有task对象存在,协程才能顺利的暂停与恢复执行,因为暂停时的变数内容都存在task对象里,就像是游戏存档一样。

2020/05/24更新
协程对象本身就能储存任务的上下文,但经过task对象的包装才能被Event Loop执行,所以说task对象负责作为Event Loop和协程对象的沟通介面。
协程是任务的实际内容,而task对象的作用是:

管理这个任务目前处在什么状态(ex. pending(等待完成)或是finished(执行完成)或是cancelled(已被取消)),并在为Event Loop和协程对象沟通时做出相应行为当协程必须中途暂停时(像example里面的await asyncio.sleep(1)),task对象会进行结尾会说明的Event:Callback注册流程,确保异步模式正常运行

其实run_until_complete也是把协程先包装成task对象后才注册到Event Loop并执行的。

asyncio.wait(tasks)
这函数的用处在于把两个example1和example2的两个协程对象包成一个大的协程对象,就是把两个小任务包成一个大任务。

await asyncio.sleep(1)
asyncio.sleep(1)简单来说就是启动一个只有一秒的倒数计时器,比较需要解释的是await这个关键字。

如果没有加入await的话,那Event Loop只会把计时器放在那边跑,就不会让example1暂停了。

如果要让await这个概念跟上一篇的异步程式概念做一个衔接的话,example1在await之前的部份就像是Callback_B,当遇到await asyncio.sleep(1),Callback_B就会注册一个"Event_D:Callback_D"进去,而Event_D就是倒数计时器倒数结束,Callback_D就是重新启动example1在await之后的部份内容。

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

下一篇教学:
python的asyncio模组(四):Event loop常用API

参考资料:
不错的asyncio语法解析
https://www.jianshu.com/p/b5e347b3a17c


关于作者: 网站小编

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

热门文章