python程序异步协程程序、asyncio

发布时间 2023-07-06 16:57:42作者: 好人~
import asyncio

async def coroutine(name, seconds):
    print(f'{name} 开始')
    await asyncio.sleep(seconds)
    print(f'{name} 结束')

async def main():
    tasks = [
        asyncio.create_task(coroutine('协程1', 2)),
        asyncio.create_task(coroutine('协程2', 1)),
        asyncio.create_task(coroutine('协程3', 3))
    ]
    await asyncio.gather(*tasks)

asyncio.run(main())

在Python中,异步的执行过程是由事件循环(event loop)来驱动的。当我们调用asyncio.run(main())时,它会创建一个事件循环,并在该循环中执行指定的协程(main函数)。

下面是程序内部异步执行的大致过程:

  • 创建事件循环:调用asyncio.run(main())会创建一个事件循环对象,该对象用于管理和调度协程的执行。

  • 启动协程:事件循环开始执行主协程,即main函数。这个协程会在事件循环中运行。

  • 创建任务:在main函数中,我们使用asyncio.create_task函数创建了三个任务。这些任务是对coroutine函数的调用,并被添加到事件循环中进行调度。

  • 并发执行:事件循环会并发地执行这些任务。它会根据调度策略(通常是基于时间片轮转的方式)在任务之间切换执行。当一个任务遇到await关键字时,事件循环会暂停该任务的执行,并切换到其他可执行的任务。

  • 等待异步操作:当协程函数中遇到await关键字时,事件循环会将控制权交给其他可执行的任务,而不是阻塞程序的执行。在我们的示例中,当await asyncio.sleep(seconds)被调用时,事件循环会安排一个定时器来等待指定的时间。

  • 任务完成:一旦一个任务完成了它的工作(在我们的示例中,等待时间结束),事件循环会恢复该任务的执行。任务会继续执行,直到遇到下一个await关键字或完成了其它操作。

  • 所有任务完成:当所有的任务都完成时,事件循环会结束,asyncio.run函数返回。程序执行完毕。

await 处的代码完成时,内部如何通知event loop:

  • 当await处的代码完成时,它会通知事件循环继续执行挂起的协程。
    具体来说,当遇到await关键字时,它会暂停当前协程的执行,并返回一个可等待对象(awaitable)。在示例代码中,await asyncio.sleep(seconds)返回一个asyncio.sleep对象,该对象是一个可等待对象。
  • 可等待对象可以是协程、任务、未来对象或任何实现了__await__方法的对象。它们可以与事件循环一起工作,并在完成时通知事件循环继续执行。

  • 当可等待对象完成时,它会通过调用其__await__方法来通知事件循环。在示例中,asyncio.sleep对象的__await__方法会告诉事件循环,等待时间已经完成。

  • 事件循环会接收到这个通知,并将控制权返回给等待该可等待对象的协程。协程会从await处继续执行,并执行下一条语句。

总结起来,当await处的代码完成时,它会通过可等待对象的__await__方法通知事件循环。事件循环会将控制权返回给挂起的协程,从await处继续执行。这种机制允许协程在等待异步操作完成时不被阻塞,并且可以与其他协程并发地执行。