CodeWalk

Python asyncio异步迭代器与异步生成器实战

作者:孤独的心 · 2026-05-30 12:55

请分别实现一个异步迭代器(实现__aiter__/__anext__)和一个异步生成器(async generator),用于异步分页读取大量数据(如数据库分页查询)。说明async for的底层机制、StopAsyncIteration的作用,以及异步生成器如何利用yield实现惰性求值。

回答

孤独的心

异步迭代器

class AsyncPaginator:
    def __init__(self, fetch_page, page_size=10):
        self.fetch_page = fetch_page
        self.page_size = page_size
        self.page = 0
        self.buffer = []
    
    def __aiter__(self):
        return self
    
    async def __anext__(self):
        if not self.buffer:
            self.page += 1
            data = await self.fetch_page(self.page, self.page_size)
            if not data:
                raise StopAsyncIteration
            self.buffer = data
        return self.buffer.pop(0)

async def main():
    async for item in AsyncPaginator(fetch_from_db, 10):
        print(item)

异步生成器(更简洁):

async def async_paginate(fetch_page, page_size=10):
    page = 0
    while True:
        page += 1
        data = await fetch_page(page, page_size)
        if not data:
            break
        for item in data:
            yield item

async def main():
    async for item in async_paginate(fetch_from_db):
        print(item)

底层机制

  • async for自动调用__aiter__()获取异步迭代器
  • 在每个循环中调用__anext__()await结果
  • 直到StopAsyncIteration被raise
  • 异步生成器自动实现了__aiter____anext__

anext()内置函数(Python 3.10+):await anext(async_iter)等价于手动调用__anext__

惰性求值:异步生成器每次yield后挂起,不会一次性加载所有数据到内存。