You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python asyncio:异步生成器无法通过zip()迭代问题咨询

问题核心:同步迭代工具无法处理异步生成器

你踩中了同步迭代与异步迭代的核心差异!普通的zip()是为同步迭代器设计的,完全无法兼容async_generator这种异步迭代器——这正是你触发错误的原因。

为什么会出错?

异步生成器实现的是__aiter__和__anext__接口,只能通过async for语法来逐个获取值;而内置的zip()会尝试调用同步迭代器的__next__方法,而异步生成器根本没有这个方法,自然会抛出异常。

解决方案:实现异步版的zip

Python标准库目前没有内置的异步zip函数,但我们可以自己实现一个,或者借助asyncio.gather()来并发处理多个异步生成器的取值逻辑。

先看错误示例(复现你的问题)

import asyncio

async def hours():
    h = 0
    while True:
        yield h
        await asyncio.sleep(3600)
        h += 1

async def minutes():
    m = 0
    while True:
        yield m
        await asyncio.sleep(60)
        m = (m + 1) % 60

async def seconds():
    s = 0
    while True:
        yield s
        await asyncio.sleep(1)
        s = (s + 1) % 60

async def main():
    # 错误用法:用同步zip处理异步生成器
    for h, m, s in zip(hours(), minutes(), seconds()):
        print(f"{h:02d}:{m:02d}:{s:02d}")

asyncio.run(main())

运行这段代码会直接报错,因为zip()试图调用异步生成器的同步__next__方法。

正确实现:自定义异步zip函数

我们可以写一个async_zip函数,用asyncio.gather()并发获取每个异步生成器的下一个值,再打包返回:

import asyncio

async def hours():
    h = 0
    while True:
        yield h
        await asyncio.sleep(3600)
        h += 1

async def minutes():
    m = 0
    while True:
        yield m
        await asyncio.sleep(60)
        m = (m + 1) % 60

async def seconds():
    s = 0
    while True:
        yield s
        await asyncio.sleep(1)
        s = (s + 1) % 60

async def async_zip(*async_generators):
    # 初始化每个异步生成器的迭代器
    iterators = [agen.__aiter__() for agen in async_generators]
    while True:
        # 并发获取所有生成器的下一个值
        values = await asyncio.gather(*[anext(it) for it in iterators])
        yield tuple(values)

async def main():
    # 使用异步zip配合async for迭代
    async for h, m, s in async_zip(hours(), minutes(), seconds()):
        print(f"{h:02d}:{m:02d}:{s:02d}")

asyncio.run(main())

这段代码会正常按时:分:秒格式输出程序启动后的时长,三个异步生成器会并发运行,不会互相阻塞。

补充说明

如果不想自己实现,也可以使用第三方库aiostream(需要先pip install aiostream),它提供了现成的异步zip工具:

from aiostream import stream, async_

async def main():
    zipped = stream.zip(hours(), minutes(), seconds())
    async for h, m, s in zipped:
        print(f"{h:02d}:{m:02d}:{s:02d}")

内容的提问来源于stack exchange,提问作者AJAY AJITH

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:56:28