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

原生协程与StopIteration:为何运行协程会抛出该异常?

Why does a native coroutine throw StopIteration when run, even though it's not an iterator?

Great question! Let's break this down step by step to clear up the confusion.

First, let's recap your example to make sure we're on the same page:

async def coro(): 
    print('hello world') 

c = coro()

As you noted, checking type(c) returns coroutine, and calling next(c) throws a TypeError because native coroutines don't implement the iterator protocol (they don't have a __next__ method). That part makes total sense.

So why does running the coroutine trigger a StopIteration?

The key here lies in Python's coroutine implementation history and how coroutines signal completion.

Native coroutines (defined with async def) evolved from generator-based coroutines (using yield/yield from). In generator-based coroutines, when the generator finished executing, it would throw StopIteration to signal that there was no more data to yield. This behavior carried over to native coroutines as a low-level mechanism to indicate that the coroutine has completed its execution.

When you manually drive a coroutine (e.g., by calling c.send(None) to start it), once the coroutine runs to its end (after printing "hello world" in your example), it will throw StopIteration to notify the caller that it's done. Here's what that looks like:

c = coro()
try:
    c.send(None)
except StopIteration:
    print("Coroutine has finished executing")

Running this code will first print hello world, then print the completion message.

If you use a proper asyncio event loop (like asyncio.run(coro())), the event loop handles this StopIteration internally, so you won't see it surface in your code. But when interacting with the coroutine directly (without the event loop), you have to handle this exception yourself.

Another thing to note: if your coroutine returns a value, that value will be stored in the value attribute of the StopIteration exception. For example:

async def coro_with_return():
    return "done"

c = coro_with_return()
try:
    c.send(None)
except StopIteration as e:
    print(f"Coroutine returned: {e.value}")  # Prints "Coroutine returned: done"

So to sum up:

  • Native coroutines aren't iterators, hence the TypeError when calling next() directly.
  • The StopIteration is a low-level signal from the coroutine to indicate it's finished, a holdover from Python's generator-based coroutine roots.
  • When using asyncio's event loop, this exception is handled for you automatically.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:54:36