在上一篇python的asyncio模组(二):异步程式设计基本概念讲解完异步程式设计的基本概念之后,就可以进入正式的主题了:
定义Event Loopimport 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对象,
2020/05/24更新
管理这个任务目前处在什么状态(ex. pending(等待完成)或是finished(执行完成)或是cancelled(已被取消)),并在为Event Loop和协程对象沟通时做出相应行为当协程必须中途暂停时(像example里面的await asyncio.sleep(1)),task对象会进行结尾会说明的Event:Callback注册流程,确保异步模式正常运行
协程对象本身就能储存任务的上下文,但经过task对象的包装才能被Event Loop执行,所以说task对象负责作为Event Loop和协程对象的沟通介面。
协程是任务的实际内容,而task对象的作用是:
其实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之后的部份内容。
下一篇教学:
python的asyncio模组(四):Event loop常用API
参考资料:
不错的asyncio语法解析
https://www.jianshu.com/p/b5e347b3a17c