Python中的异步生成器与异步推导式
字数 1976 2025-12-10 14:34:01

Python中的异步生成器与异步推导式


1. 知识点描述

在Python中,异步生成器是使用async def定义、并包含yield语句的协程函数,用于异步生成值序列。异步推导式是类似列表推导式的语法,但通过async for迭代异步可迭代对象,生成列表、集合、字典等集合。这两者是异步编程中处理流式数据或异步集合操作的核心工具,常用于asyncio环境中高效处理I/O密集型任务。


2. 异步生成器的核心机制

2.1 基本语法

异步生成器函数通过async def定义,并在函数体内使用yield返回数据:

async def async_gen():
    for i in range(3):
        await asyncio.sleep(0.1)  # 模拟异步操作
        yield i
  • 调用async_gen()不会执行函数体,而是返回一个异步生成器对象(类型为async_generator)。
  • 异步生成器实现了异步迭代器协议,即需通过__aiter__()__anext__()方法支持异步迭代。

2.2 异步迭代协议

异步生成器对象的核心方法:

  • __aiter__():返回自身(异步迭代器)。
  • __anext__():在每次迭代时恢复生成器执行,返回一个awaitable对象(通常是协程),解析后得到yield的值。若生成器结束,抛出StopAsyncIteration异常。

示例:手动迭代异步生成器

import asyncio

async def consume_async_gen():
    ag = async_gen()           # 创建异步生成器对象
    async for value in ag:     # 使用 async for 迭代
        print(value)           # 输出 0, 1, 2

3. 异步推导式的工作原理

3.1 异步推导式的类型

Python支持四种异步推导式(语法在async for前放置集合类型):

  1. 异步列表推导式[i async for i in async_gen()]
  2. 异步集合推导式{i async for i in async_gen()}
  3. 异步字典推导式{i: i*2 async for i in async_gen()}
  4. 异步生成器表达式(i async for i in async_gen())

3.2 执行过程

以异步列表推导式为例:

async def demo():
    data = [i async for i in async_gen()]  # 结果: [0, 1, 2]

执行步骤:

  1. 解释器识别async for语法,创建隐式的异步迭代循环。
  2. 循环内部:
    • 调用异步生成器的__anext__(),返回awaitable对象。
    • 通过await等待该对象,获取值i
    • i加入临时列表。
  3. StopAsyncIteration抛出时,结束循环并返回完整列表。

4. 与同步版本的对比

特性 同步生成器/推导式 异步生成器/推导式
定义关键字 def + yield async def + yield
迭代方式 for循环 async for循环
推导式语法 [i for i in gen()] [i async for i in async_gen()]
暂停机制 yield暂停,保存本地状态 yieldawait处均可暂停

5. 实际应用场景

场景1:异步流式数据处理

import aiohttp

async def fetch_urls(urls):
    async with aiohttp.ClientSession() as session:
        for url in urls:
            async with session.get(url) as resp:
                yield await resp.text()  # 异步生成每个页面内容

# 使用异步推导式收集数据
async def collect_pages(urls):
    pages = [text async for text in fetch_urls(urls)]  # 并发请求并收集结果
    return pages

场景2:异步过滤与转换

# 异步生成器表达式作为过滤管道
async def filter_data(source_gen):
    filtered = (item.upper() async for item in source_gen if item.startswith("A"))
    async for val in filtered:  # 惰性计算
        process(val)

6. 注意事项与常见错误

  1. 必须使用async for迭代
    错误:for i in async_gen()(同步循环无法驱动)。
    正确:async for i in async_gen()

  2. 异步推导式需在协程函数内使用
    异步推导式本身返回awaitable对象,需在协程中解析:

    async def main():
        data = [i async for i in async_gen()]  # 直接返回列表
        # 若在非协程中使用,需用asyncio.run()包装
    
  3. 资源管理
    异步生成器中可使用async with管理资源(如数据库连接),确保yield前后资源正确释放:

    async def read_lines(connection):
        async with connection.cursor() as cur:
            await cur.execute("SELECT * FROM table")
            async for row in cur:
                yield row
    

7. 底层实现简析

  • 异步生成器对象由PyAsyncGenObject结构体表示,内部状态机跟踪yieldawait位置。
  • 异步推导式在字节码层面生成GET_AITERSET_ANEXT等指令,通过事件循环驱动迭代。
  • 异步生成器最终需调用aclose()关闭,防止资源泄漏(通常由async for自动处理)。

8. 总结

  • 异步生成器通过async defyield结合,实现惰性的异步数据流。
  • 异步推导式提供简洁语法,支持对异步可迭代对象进行集合转换。
  • 两者均依赖async for驱动,是异步编程中处理批量I/O操作的高效工具。
Python中的异步生成器与异步推导式 1. 知识点描述 在Python中, 异步生成器 是使用 async def 定义、并包含 yield 语句的协程函数,用于异步生成值序列。 异步推导式 是类似列表推导式的语法,但通过 async for 迭代异步可迭代对象,生成列表、集合、字典等集合。这两者是异步编程中处理流式数据或异步集合操作的核心工具,常用于 asyncio 环境中高效处理I/O密集型任务。 2. 异步生成器的核心机制 2.1 基本语法 异步生成器函数通过 async def 定义,并在函数体内使用 yield 返回数据: 调用 async_gen() 不会执行函数体,而是返回一个 异步生成器对象 (类型为 async_generator )。 异步生成器实现了 异步迭代器协议 ,即需通过 __aiter__() 和 __anext__() 方法支持异步迭代。 2.2 异步迭代协议 异步生成器对象的核心方法: __aiter__() :返回自身(异步迭代器)。 __anext__() :在每次迭代时恢复生成器执行,返回一个 awaitable 对象(通常是协程),解析后得到 yield 的值。若生成器结束,抛出 StopAsyncIteration 异常。 示例:手动迭代异步生成器 3. 异步推导式的工作原理 3.1 异步推导式的类型 Python支持四种异步推导式(语法在 async for 前放置集合类型): 异步列表推导式 : [i async for i in async_gen()] 异步集合推导式 : {i async for i in async_gen()} 异步字典推导式 : {i: i*2 async for i in async_gen()} 异步生成器表达式 : (i async for i in async_gen()) 3.2 执行过程 以异步列表推导式为例: 执行步骤: 解释器识别 async for 语法,创建隐式的异步迭代循环。 循环内部: 调用异步生成器的 __anext__() ,返回 awaitable 对象。 通过 await 等待该对象,获取值 i 。 将 i 加入临时列表。 当 StopAsyncIteration 抛出时,结束循环并返回完整列表。 4. 与同步版本的对比 | 特性 | 同步生成器/推导式 | 异步生成器/推导式 | |------------------|-----------------------------|--------------------------------| | 定义关键字 | def + yield | async def + yield | | 迭代方式 | for 循环 | async for 循环 | | 推导式语法 | [i for i in gen()] | [i async for i in async_gen()] | | 暂停机制 | 遇 yield 暂停,保存本地状态 | 在 yield 和 await 处均可暂停 | 5. 实际应用场景 场景1:异步流式数据处理 场景2:异步过滤与转换 6. 注意事项与常见错误 必须使用 async for 迭代 : 错误: for i in async_gen() (同步循环无法驱动)。 正确: async for i in async_gen() 。 异步推导式需在协程函数内使用 : 异步推导式本身返回 awaitable 对象,需在协程中解析: 资源管理 : 异步生成器中可使用 async with 管理资源(如数据库连接),确保 yield 前后资源正确释放: 7. 底层实现简析 异步生成器对象由 PyAsyncGenObject 结构体表示,内部状态机跟踪 yield 和 await 位置。 异步推导式在字节码层面生成 GET_AITER 、 SET_ANEXT 等指令,通过事件循环驱动迭代。 异步生成器最终需调用 aclose() 关闭,防止资源泄漏(通常由 async for 自动处理)。 8. 总结 异步生成器通过 async def 和 yield 结合,实现惰性的异步数据流。 异步推导式提供简洁语法,支持对异步可迭代对象进行集合转换。 两者均依赖 async for 驱动,是异步编程中处理批量I/O操作的高效工具。