异步迭代器报错RuntimeError: Task got bad yield: 1 求助排查问题
Hey there! Let's figure out why you're hitting that RuntimeError: Task got bad yield: 1 with your async iterator code. The issue boils down to a key rule in Python's async/await system that's easy to miss when starting out.
错误原因的核心
Your Awaitable class's __await__ method is yielding plain integer values (1, 2), but Python's async runtime strictly enforces that __await__ can only yield valid awaitable objects (like asyncio.Future, asyncio.Task, or other objects that implement their own __await__ method). Plain numbers don't qualify, so the runtime throws that "bad yield" error. PEP 492 explicitly defines this requirement for awaitable objects.
修正方案:符合规范的异步迭代器
It looks like you're trying to build an async iterator that produces values 1 and 2. Let's adjust your code to fit Python's async model properly. Here are two approaches depending on your needs:
方案1:直接在异步迭代器中处理逻辑(简单场景首选)
We can handle the iteration state directly in the AsyncIterator class, and use a proper awaitable (like asyncio.sleep to simulate async work) if needed:
import asyncio class AsyncIterator: def __init__(self): self.i = 1 def __aiter__(self): return self async def __anext__(self): if self.i < 3: current_value = self.i print(f"yield {current_value}") self.i += 1 # 模拟异步操作(可选,展示正确的await用法) await asyncio.sleep(0) return current_value else: # 异步迭代器结束必须抛出这个异常 raise StopAsyncIteration # 测试异步迭代器 async def main(): async for num in AsyncIterator(): print(f"Received: {num}") asyncio.run(main())
方案2:使用合法的自定义Awaitable类(如果需要封装异步逻辑)
If you really need a custom Awaitable class (for example, to wrap a specific async operation), make sure its __await__ method only yields valid awaitable objects:
import asyncio class Awaitable: def __init__(self, value): self.value = value def __await__(self): # 委托给一个合法的可等待对象(这里用asyncio.sleep做示例) yield from asyncio.sleep(0).__await__() return self.value class AsyncIterator: def __init__(self): self.i = 1 def __aiter__(self): return self async def __anext__(self): if self.i < 3: value = await Awaitable(self.i) print(f"yield {self.i}") self.i += 1 return value else: raise StopAsyncIteration # 测试代码 async def main(): async for num in AsyncIterator(): print(f"Received: {num}") asyncio.run(main())
关键总结
__await__methods cannot yield non-awaitable values like integers or strings. Always yield valid awaitable objects if you're implementing this method.- For simple async iteration, handle the state directly in the
__anext__method of your async iterator and raiseStopAsyncIterationwhen done—this follows the standard pattern for both sync and async iterators.
内容的提问来源于stack exchange,提问作者Mykola Fenyk

