返回

从1到∞精通Python(11):async/await的源码实现

后端

要真正掌握asyncio异步机制的精髓,除了深入了解asyncio内部逻辑,还需要透彻理解Python原语async/await的含义。只有这样,才能清晰地认识到异步任务的定义和执行机制。本文将带你踏上一次详尽的源码分析之旅,揭开async/await的神秘面纱。

async/await的底层机制

async/await是Python 3.5中引入的协程支持特性。协程是一种轻量级的并发机制,它允许函数在挂起时让出控制权,然后在需要时继续执行。

当一个函数被声明为async时,它就变成了一个协程。该函数中的await表达式会挂起协程,直到等待的操作(通常是I/O操作)完成。在此期间,协程会让出控制权,使其他协程有机会执行。

为了实现协程,Python使用了一个称为事件循环的机制。事件循环不断检查挂起的协程,并在操作完成时恢复它们的执行。这使得Python可以同时处理多个并发任务,而无需使用多线程或多进程等传统并发技术。

asyncio中的async/await

asyncio是Python中用于异步编程的标准库。它提供了一组API,可以轻松编写基于事件循环的并发代码。asyncio中的async/await与原生Python中的async/await具有相同的语法和语义,但它们与asyncio事件循环紧密集成。

当你在asyncio中使用async/await时,asyncio事件循环会自动管理协程的挂起和恢复。这极大地简化了异步编程,因为你不再需要手动管理事件循环。

源码分析

为了更深入地理解async/await的实现,让我们分析一下Python 3.10版本的底层源码。

async函数的声明

async函数的声明如下:

def async_function():
    ...

async指示该函数是一个协程。函数体可以包含await表达式,这些表达式会挂起协程。

await表达式的实现

await表达式在__await__()方法中实现。该方法是collections.abc.Awaitable抽象基类的子类:

class Awaitable:
    def __await__(self):
        ...

对于一个async函数,__await__()方法返回一个协程。当await表达式被执行时,它会调用__await__()方法,并挂起协程。

事件循环的集成

asyncio事件循环通过Task类与async/await集成。Task类代表一个异步任务,它由事件循环管理:

class Task:
    def __init__(self, coro):
        ...

当创建async函数时,会创建一个Task对象并将其添加到事件循环中:

async def async_function():
    ...

task = asyncio.create_task(async_function())

事件循环不断运行,检查挂起的协程,并在操作完成时恢复它们的执行。

总结

通过对async/await底层源码的分析,我们揭开了异步编程的神秘面纱。我们了解到async/await如何实现协程,以及asyncio如何利用事件循环管理异步任务。这让我们对Python并发编程有了更深入的理解,并为编写高效的异步代码提供了坚实的基础。