例程一 协程A里面调用了协程B和协程C,添加事件循环时只添加了协程A,则协程B和协程C的启动顺序是按照被协程A调用的先后顺序执行:
import asyncio
import sys
import time
async def func_1(): #使用 await 关键字将func_1() 定义为异步函数(协程)
print("func_1 runnig:")
await asyncio.sleep(5)
print("func_1 done")
async def func_2():
print("func_2 running:")
await asyncio.sleep(0)
print("func_2 done")
async def func_3():
await func_1()
await func_2()
asyncio.get_event_loop().create_task(func_3()) #使用asyncio.get_event_loop().create_task()将 func_3() 添加进事件循环,开始运行协程
运行结果:
<Task pending coro=<func_3() running at <ipython-input-18-813dfcba959a>:15>>
func_1 runnig:
func_1 done
func_2 running:
func_2 done
分析:
例程一中,通过协程func_3()
依次调用协程func_1()
和func_2()
,然后通过asyncio.get_event_loop().create_task(func_3())
语句将func_3()
添加到event_loop
里进行运行,这种方式,func_3()
所调用的协程是依次顺序执行的
例程二 一次性添加进event_loop()
里的协程是按照事件循环添加任务的先后顺序以及被添加协程执行快慢来,优先执行运行时间短的顺序来执行的
import asyncio
import sys
import time
async def func_1():
print("func_1 running:")
await asyncio.sleep(5)
print("func_1 done")
async def func_2():
print("func_2 running:")
await asyncio.sleep(1)
print("func_2 done")
task = [func_1(),func_2()]
asyncio.get_event_loop().create_task(asyncio.wait(task)) #注意这里要加asyncio.wait()将其作为协程加入,否则报错!
运行结果:
<Task pending coro=<wait() running at C:\Users\Administrator\Anaconda3\lib\asyncio\tasks.py:335>>
func_1 running:
func_2 running:
func_2 done
func_1 done
分析:
例程二中,通过创建协程列表task
,然后用列表一次性添加进event_loop
,这种情况下,添加进event_loop
里的协程是按照执行时间的快慢执行的,先执行时间短的,再执行时间长的。这里才是真正的异步执行。
例程三 添加协程(异步函数)到event_loop
中,如果这些协程都是嵌套协程(协程函数体内部调用了其他的协程),则按照添加顺序和时间快慢的顺序执行协程
import asyncio
import sys
import time
async def func_1():
print("func_1 runnig:")
await asyncio.sleep(5)
print("func_1 done")
async def func_2():
print("func_2 running:")
await asyncio.sleep(2)
print("func_2 done")
async def func_3():
print("func_3 running:")
await asyncio.sleep(0)
print("func_3 done")
task = [func_1(),func_2(),func_3()]
asyncio.get_event_loop().create_task(asyncio.wait(task))
运行结果:
<Task pending coro=<wait() running at C:\Users\Administrator\Anaconda3\lib\asyncio\tasks.py:335>>
func_1 runnig:
func_2 running:
func_3 running:
func_3 done
func_2 done
func_1 done
分析:
例程三中,对于协程func_1(),func_2(),func_3()
,在每个协程中都通过await
调用了协程asyncio.sleep()
,因此在这三个协程添加到task
协程列表里,并通过aysncio.get_event_loop().create_task()
添加到事件循环中时,这三个协程是依添加顺序和执行时间快慢来执行的。
例程四 添加协程(异步函数)到event_loop
中,如果这些协程都是普通协程(协程函数体内没有调用其他的协程),则协程的执行顺序是随机的?
import asyncio
import sys
import time
async def func_1():
print("func_1 runnig:")
time.sleep(5)
print("func_1 done")
async def func_2():
print("func_2 running:")
time.sleep(2)
print("func_2 done")
async def func_3():
print("func_3 running:")
time.sleep(0)
print("func_3 done")
task = [func_1(),func_2(),func_3()]
asyncio.get_event_loop().create_task(asyncio.wait(task))
第一次运行结果:
<Task pending coro=<wait() running at C:\Users\Administrator\Anaconda3\lib\asyncio\tasks.py:335>>
func_2 running:
func_2 done
func_1 runnig:
func_1 done
func_3 running:
func_3 done
第二次运行结果:
<Task pending coro=<wait() running at C:\Users\Administrator\Anaconda3\lib\asyncio\tasks.py:335>>
func_1 runnig:
func_1 done
func_3 running:
func_3 done
func_2 running:
func_2 done
第三次运行结果:
<Task pending coro=<wait() running at C:\Users\Administrator\Anaconda3\lib\asyncio\tasks.py:335>>
func_2 running:
func_2 done
func_3 running:
func_3 done
func_1 runnig:
func_1 done
分析:
例程四中,对于协程func_1(),func_2(),func_3()
,在每个协程中都调用了time.sleep()
函数,这个并不是协程函数而只是普通的函数,当把func_1(),func_2(),func_3()
这三个协程添加到task
协程列表里,并通过aysncio.get_event_loop().create_task()
添加到事件循环后,这三个协程的执行顺序并不是按照被依添加的顺序或者执行时间快慢来执行的,而是处于一种随机的顺序。通过以上几个例子可以发现,被添加到event_loop
里的协程,对于嵌套协程,则事件循环时会依照添加顺序依次启动执行被添加的协程;对于普通协程,则事件循环时执行顺序是随机不确定的。
例程五 添加协程(异步函数)到event_loop
中,如果被添加的协程中既有内部调用其他协程函数,也有没有调用其他的协程只是普通函数体的协程,则协程的执行顺序是怎样的?
import asyncio
import sys
import time
async def func_1():
print("func_1 runnig:")
await asyncio.sleep(5)
print("func_1 done")
async def func_2():
print("func_2 running:")
await asyncio.sleep(2)
print("func_2 done")
async def func_3():
print("func_3 running:")
time.sleep(0)
print("func_3 done")
task = [func_1(),func_2(),func_3()]
asyncio.get_event_loop().create_task(asyncio.wait(task))
运行结果:
<Task pending coro=<wait() running at C:\Users\Administrator\Anaconda3\lib\asyncio\tasks.py:335>>
func_3 running:
func_3 done
func_1 runnig:
func_2 running:
func_2 done
func_1 done
分析:
添加协程(异步函数)到event_loop
中,如果被添加的协程中既有嵌套协程,如func_1(),func_2()
,也有普通协程,如func_3
,则优先执行普通协程。
总结
对于使用aysncio.get_event_loop().create_task()
添加协程到事件循环,本质上是对协程进行异步执行,执行顺序基本上是按照被添加的顺序来启动协程的,当同时存在普通协程(内部没有调用其他协程函数)和嵌套协程(内部调用了其他协程函数)时,优先级如下:
普通协程 > 嵌套协程