python协程asynio深入解析

先上代码:

import asyncio

async def test():
    print('one')
    await asyncio.sleep(1)
    print('two')

async def main():
    a=asyncio.create_task(test())
    b=asyncio.create_task(test())
    c=asyncio.create_task(test())
    print('hello')
    await a,b,c

asyncio.run(main())

运行结果很完美:

hello
one
one
one
two
two
two

修改代码,删除await a,b,c

import asyncio

async def test():
    print('one')
    await asyncio.sleep(1)
    print('two')

async def main():
    a=asyncio.create_task(test())
    b=asyncio.create_task(test())
    c=asyncio.create_task(test())
    print('hello')

asyncio.run(main())
hello
one
one
one

Process finished with exit code 0

可以发现test()执行了,但是没有'two'。再次修改代码增加

import asyncio

async def test():
    print('one')
    await asyncio.sleep(1)
    print('two')

async def main():
    a=asyncio.create_task(test())
    b=asyncio.create_task(test())
    c=asyncio.create_task(test())
    print('hello')
    await asyncio.sleep(1)

asyncio.run(main())

结果为:

hello
one
one
one
two
two
two

实际执行过程为:

1、asyncio.run(main()),程序进入 main() 函数,事件循环开启;

2、任务a、b、c被创建,并进入事件循环等待运行;运行到 print时,输出 'hello';

3、如果运行到await,则从当前的主任务中切出,事件调度器开始调度 a

4、在a中打印'one',运行到 await asyncio.sleep(1),从当前任务切出,事件调度器开始调度 b

5、在b中打印'one',运行到 await asyncio.sleep(1),从当前任务切出,事件调度器开始调度 c

6、在c中打印'one',运行到 await asyncio.sleep(1),从当前任务切出。

7、如果后续程序,如第二段代码中没有await,主程序认为程序运行完毕,则结束进程,不会打印'two'。

8、如果await a,b,c 则主程序会等待a、b、c执行完毕。

9、如果main函数中没有await a,b,c,而是await  asyncio.sleep(1),则a、b、c依旧有时间执行完程序,所以会输出'two',但如果await  asyncio.sleep(0.5)则a、b、c在执行完毕前程序就会被杀死,所以依旧不会输出'two'。

如果我们想给某些协程任务限定运行时间,一旦超时就取消,或者协程运行错误应该怎么处理呢?这里贴上某位大佬的代码:


import asyncio

async def worker_1():
    await asyncio.sleep(1)
    return 1

async def worker_2():
    await asyncio.sleep(2)
    return 2 / 0

async def worker_3():
    await asyncio.sleep(3)
    return 3

async def main():
    task_1 = asyncio.create_task(worker_1())
    task_2 = asyncio.create_task(worker_2())
    task_3 = asyncio.create_task(worker_3())

    await asyncio.sleep(2)
    task_3.cancel()

    res = await asyncio.gather(task_1, task_2, task_3, return_exceptions=True)
    print(res)

%time asyncio.run(main())

########## 输出 ##########

[1, ZeroDivisionError('division by zero'), CancelledError()]
Wall time: 2 s

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值