python 异步生成器执行过程

1,背景:

比较好奇异步生成器是如何执行的,协程如何启动,什么时候挂起,调度协程的事件循环在什么节点启动。

2,观察协程执行过程

代码如下:总共有一个主协程+3个task协程,整体过程如下:

  • Step1:首先通过asyncio.run启动事件循环(该事件循环用于协调所有协程的运行),运行一个协程(该协程执行下面main_process的处理,这里我们暂时叫它主协程)
  • Step2:主协程里面通过asyncio.create_task生成了三个新的协程,task1,2,3。所以目前总共有主协程+task1,2,3,总共4个协程。
  • Step3:事件循环会在这四个协程中进行调度从这4个中,选取一个准备完毕可以执行的协程,运行该协程,直到协程挂起(下面的await处理)。协程挂起之后,事件循环会将继续选取另外一个准备完毕的协程,继续执行。
# 定义一个异步的生成器
async def generator(name):
    for i in range(3):
        print(f"【{name}】-开始异步操作: {i},协程挂起2s")
        await asyncio.sleep(3)  # 这里模拟异步耗时操作(比如文件io,网络读取等),协程挂起3s
        print(f"【{name}】-异步操作完成,生成: {i}")
        yield i

# 定义一个异步函数来处理生成器
async def process_generator(name):
    # 进入协程处理
    print(f"【{name}】进入协程处理:")
    # 如果是普通的for循环,是同步执行,会在协程中全部执行完毕,再进入到后续处理
    # for item in range(0,2):
    #    print(f'【{name}】普通的生成器:{item}')

    # async for:异步迭代的语法,它允许你以异步的方式遍历异步迭代器。
    async for item in generator(name):
        print(f"【{name}】协程处理继续: 生成{item}")
        print(f"【{name}】协程处理继续: 即将进入下一个生成")

# 主函数
async def main_process():
    print('【主协程】进入main处理')
    print('【主协程】生成 协程 task1')
    task1 = asyncio.create_task(process_generator('task1')) #生成一个新的协程
    print('【主协程】生成 协程 task2')
    task2 = asyncio.create_task(process_generator('task2')) #生成一个新的协程
    print('【主协程】生成 协程 task3')
    task3 = asyncio.create_task(process_generator('task3')) #生成一个新的协程

    # 获取当前事件循环中的所有任务
    tasks = asyncio.all_tasks()
    print(f"【主协程】当前事件循环中有 {len(tasks)} 个任务(一个主协程+3个task协程)")
    # 等待所有任务完成
    print(f"【主协程】挂起,等待task1完成")
    await task1
    print(f"【主协程】挂起,等待task2完成")
    await task2
    print(f"【主协程】挂起,等待task3完成")
    await task3
    print('【主协程】全部完成')

# 启动事件循环(该事件循环用于协调所有协程的运行),运行一个协程,执行main_process函数
asyncio.run(main_process())

执行结果:

【主协程】进入main处理
【主协程】生成 协程 task1
【主协程】生成 协程 task2
【主协程】生成 协程 task3
【主协程】当前事件循环中有 4 个任务(一个主协程+3个task协程)
【主协程】挂起,等待task1完成
【task1】进入协程处理:
【task1】-开始异步操作: 0,协程挂起2s
【task2】进入协程处理:
【task2】-开始异步操作: 0,协程挂起2s
【task3】进入协程处理:
【task3】-开始异步操作: 0,协程挂起2s
【task1】-异步操作完成,生成: 0
【task1】协程处理继续: 生成0
【task1】协程处理继续: 即将进入下一个生成
【task1】-开始异步操作: 1,协程挂起2s
【task2】-异步操作完成,生成: 0
【task2】协程处理继续: 生成0
【task2】协程处理继续: 即将进入下一个生成
【task2】-开始异步操作: 1,协程挂起2s
【task3】-异步操作完成,生成: 0
【task3】协程处理继续: 生成0
【task3】协程处理继续: 即将进入下一个生成
【task3】-开始异步操作: 1,协程挂起2s
【task1】-异步操作完成,生成: 1
【task1】协程处理继续: 生成1
【task1】协程处理继续: 即将进入下一个生成
【task1】-开始异步操作: 2,协程挂起2s
【task2】-异步操作完成,生成: 1
【task2】协程处理继续: 生成1
【task2】协程处理继续: 即将进入下一个生成
【task2】-开始异步操作: 2,协程挂起2s
【task3】-异步操作完成,生成: 1
【task3】协程处理继续: 生成1
【task3】协程处理继续: 即将进入下一个生成
【task3】-开始异步操作: 2,协程挂起2s
【task1】-异步操作完成,生成: 2
【task1】协程处理继续: 生成2
【task1】协程处理继续: 即将进入下一个生成
【task2】-异步操作完成,生成: 2
【task2】协程处理继续: 生成2
【task2】协程处理继续: 即将进入下一个生成
【task3】-异步操作完成,生成: 2
【task3】协程处理继续: 生成2
【task3】协程处理继续: 即将进入下一个生成
【主协程】挂起,等待task2完成
【主协程】挂起,等待task3完成
【主协程】全部完成

Process finished with exit code 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值