Python3.9中__anext__用yield时报async_generator无法用于await错误如何解决
问题根源
- 你在
async def __anext__方法中使用了yield关键字,这会让__anext__变成异步生成器函数,调用该方法返回的是异步生成器对象,而不是异步迭代器协议要求的、可以被await后返回单个元素/抛出终止异常的协程对象,直接对异步生成器对象执行await就会触发你遇到的类型错误。 - 你的
StopAsyncIteration没有加raise关键字,不会实际抛出异常终止迭代,同时__anext__内部不应该用async for遍历整个底层生成器,__anext__每次被调用仅需要返回一个下一个迭代元素。 - 用
type(payload) != str判断类型的写法不够严谨,无法兼容str子类的场景,推荐用isinstance方法。
修复方案
有两种可选的实现方式,你可以按需选择:
方案1:直接使用异步生成器函数(更简洁,无需自定义类)
你的需求本质是过滤generate_fb_payload的输出,遇到str类型就终止迭代,直接写异步生成器函数即可,不需要自定义迭代器类:
async def payload_session_generator(): async for payload in generate_fb_payload(): if isinstance(payload, str): break yield payload
使用方式和你原有逻辑兼容:
# 生成迭代器实例 self._iter = payload_session_generator() # 取下一个元素 chunk = await anext(self._iter) # 也可以用你原有的写法:chunk = await self._iter.__anext__()
方案2:修正自定义异步迭代器类的实现
如果你需要保留自定义类的结构,需要把底层生成器的迭代状态存储在实例属性中,修改__anext__的实现符合异步迭代器协议:
class Payload_Session_Generator: def __init__(self): # 初始化时持有底层异步生成器 self._inner_gen = generate_fb_payload() async def __anext__(self): # 每次调用仅获取一个下一个元素 payload = await anext(self._inner_gen) if isinstance(payload, str): # 遇到字符串类型抛出终止异常,必须加raise关键字 raise StopAsyncIteration return payload def __aiter__(self): return self
使用方式和你原有逻辑完全一致,不需要修改调用侧的代码。
注:如果你的Python版本低于3.10,没有内置的anext全局函数,可以将await anext(xxx)替换为await xxx.__anext__(),和你原有调用逻辑完全兼容。
内容的提问来源于stack exchange,提问作者sonium
相关产品推荐
相关产品推荐

