GeneratorExit是生成器关闭时抛出的异常,调用close()方法会触发它。正确做法是在except GeneratorExit块中清理资源并return,避免抛出新异常或误用raise StopIteration,否则可能引发RuntimeWarning或RuntimeError。异步生成器需注意对应CancelledError。

在使用python生成器时,GeneratorExit 是一种特殊的异常,它会在生成器被显式关闭或垃圾回收时抛出。正常情况下,生成器函数应优雅地处理这个异常,否则可能引发 RuntimeWarning: coroutine '...' was never awaited 或其他意外行为。
GeneratorExit 是什么?
当调用生成器对象的 close() 方法时,Python 会向生成器内部抛入一个 GeneratorExit 异常,通知其终止运行。如果生成器没有正确处理该异常,或者在处理过程中又抛出了其他异常(非 GeneratorExit 或 StopIteration),就会触发错误警告。
常见报错示例:
RuntimeError: generator raised StopIteration
或:
立即学习“Python免费学习笔记(深入)”;
Warning: coroutine was never awaited
正确处理 GeneratorExit 的方法
为了确保生成器能安全退出,应在 try...finally 或 try...except 块中捕获 GeneratorExit,并在处理后正常退出。
示例:安全关闭生成器
def my_generator(): try: while True: yield "数据" except GeneratorExit: # 清理资源,如关闭文件、网络连接等 print("生成器正在关闭") # 必须不再抛出异常,或仅 raise return # 正确方式:直接返回或 break <p>g = my_generator() next(g) g.close() # 触发 GeneratorExit
关键点:
- 使用
except GeneratorExit:捕获退出信号 - 执行必要的清理操作
- 通过
return正常退出,不要再次抛出异常 - 避免在 except 块中使用
raise Exception()
避免在生成器中误用 StopIteration
在生成器内部手动抛出 StopIteration 来结束迭代是不推荐的,这可能导致解释器层面的错误,尤其是在 Python 3.7+ 中。
错误写法:
def bad_gen(): yield 1 raise StopIteration # 不推荐
正确做法是使用 return:
def good_gen(): yield 1 return # 自然结束生成器
协程中的注意事项
如果你使用的是 async 生成器或协程(async def),则需注意 GeneratorExit 对应的是 CancelledError 或 asyncio.CancelledError,处理逻辑类似,但异常类型不同。
对于异步生成器:
async def async_gen(): try: while True: yield "异步数据" except GeneratorExit: print("异步生成器关闭") return
基本上就这些。只要记得在生成器中捕获 GeneratorExit 并干净退出,就不会出现退出异常问题。关键是不要在处理退出时制造新的异常。