关于使用python 协程模块asyncio创建协程添加进get_event_loop后协程启动顺序分析

1 篇文章 0 订阅
1 篇文章 0 订阅

例程一 协程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()添加协程到事件循环,本质上是对协程进行异步执行,执行顺序基本上是按照被添加的顺序来启动协程的,当同时存在普通协程(内部没有调用其他协程函数)和嵌套协程(内部调用了其他协程函数)时,优先级如下:
普通协程 > 嵌套协程

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
asyncio 模块中,协程和任务是两个重要的概念。 协程是一种轻量级的线程,可以在单个线程中实现并发。在 asyncio 中,协程通过 async/await 语法来定义。协程可以被看作是一种特殊的函数,它们可以被暂停和恢复,这使得它们非常适合与异步编程模型结合使用。 任务是对协程的封装,它包含了一个协程对象以及一些额外的信息,比如任务的状态、优先级等。任务可以被看作是对协程的一种调度,它可以被加入事件循环中,由事件循环来负责调度。 在 asyncio 中,我们通常使用 async 关键字来定义协程,例如: ```python async def foo(): # 协程代码 ``` 定义好协程之后,我们可以将它封装成一个任务,然后将任务加入事件循环中,例如: ```python import asyncio async def foo(): # 协程代码 loop = asyncio.get_event_loop() task = loop.create_task(foo()) loop.run_until_complete(task) ``` 在上面的代码中,我们使用 get_event_loop() 方法来获取事件循环对象,然后使用 create_task() 方法来将 foo() 协程封装成一个任务,并将任务加入事件循环中,最后使用 run_until_complete() 方法来运行事件循环。这样,foo() 协程就会被异步执行了。 当我们需要同时运行多个协程时,可以使用 asyncio.gather() 方法来将多个协程封装成一个任务集合,例如: ```python import asyncio async def foo(): # 协程代码 async def bar(): # 协程代码 loop = asyncio.get_event_loop() tasks = [loop.create_task(foo()), loop.create_task(bar())] loop.run_until_complete(asyncio.gather(*tasks)) ``` 在上面的代码中,我们使用 create_task() 方法将 foo() 和 bar() 协程封装成两个任务,并将这两个任务加入事件循环中。然后使用 asyncio.gather() 方法将这两个任务封装成一个任务集合,并使用 run_until_complete() 方法来运行这个任务集合。这样,foo() 和 bar() 协程就会被同时异步执行了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值