如何让生成器支持 throw() 抛异常到生成器内部

发布时间 - 2026-01-27 00:00:00    点击率:
只有含yield表达式(如received = yield value)的生成器才能用throw()触发except捕获;yield语句无法中断执行,throw()将直接终止生成器。

生成器必须用 yield 表达式而非 yield 语句

Python 中,只有函数体内包含 yield 表达式(即出现在等号右侧、能接收值的 yield),才能通过 throw() 向内部抛异常并被 except 捕获。如果只写 yield 语句(如 yield 42),它仍可迭代,但 throw() 只会终止生成器,无法进入 except 块。

常见错误现象:Generator.throw() 调用后直接抛出 StopIteration 或原异常未被捕获,本质是控制流没停在可中断的 yield 表达式上。

  • 正确写法:received = yield value —— 此处 yield 是表达式,暂停点可接收值或异常
  • 错误写法:yield value(无赋值)—— 控制流经过即继续,throw() 无法“插入”到执行中
  • 即使不打算接收值,也应写成 _ = yield valueyield value; continue 后补一个空 yield 表达式

throw() 必须在生成器暂停时调用

throw() 不是“发消息”,而是向当前暂停点注入异常。若生成器已结束(StopIteration 已 raise)、尚未启动(还没第一次 next()send(None)),或正在运行中(比如卡在某个循环里没遇到 yield),调用 throw() 都会报 RuntimeError: generator already executing 或直接失败。

使用场景:常用于协程式状态机,比如等待用户输入时,外部想强制中断并清理资源。

  • 首次启动必须用 next(gen)gen.send(None),否则 throw() 无效
  • 每次 throw() 后,生成器必须再次被

    驱动(next()send()),否则停留在抛异常后的暂停点
  • 若生成器在 try/finally 中,throw() 触发异常时 finally 仍会执行

异常类型需与 except 匹配,且不能跳过 yield

生成器内 except 能捕获 throw() 的异常,前提是该 except 所在的 try 块覆盖了当前 yield 表达式所在的位置,并且异常类型一致。Python 不支持“跳转式捕获”——异常不会向上越过未激活的 try 块。

参数差异:gen.throw(TypeError, "msg") 等价于 gen.throw(TypeError("msg")),但推荐传入已实例化的异常对象,避免某些版本兼容问题。

  • yieldtry 外,throw() 会直接冒泡,不会进 except
  • except BaseException: 可捕获所有,但会吞掉 GeneratorExitSystemExit,慎用
  • 捕获后若不 returnyield,生成器立即结束;若继续 yield,则恢复迭代流程

实际例子:带错误恢复的计数生成器

下面是一个能响应 throw(ValueError) 并重置计数的生成器:

def counter():
    i = 0
    while True:
        try:
            i += 1
            # 必须是 yield 表达式,哪怕不接收值
            _ = yield i
        except ValueError:
            print("resetting...")
            i = 0

调用方式:

g = counter()
next(g) # → 1
next(g) # → 2
g.throw(ValueError) # 打印 resetting...,不抛异常
next(g) # → 1(已重置)

容易踩的坑:忘记在 throw() 后调用 next()send(),结果生成器停在 except 块末尾,下一次 next() 才真正产出值——这个延迟行为常被忽略。


# python  # ai  # try  # throw  # continue  # 循环  # raise  # finally  # 对象  # 停在  # 会报  # 是一个  # 迭代  # 还没  # 首次  # 出现在  # 只会  # 不支持  # 跳转 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何获取上海专业网站定制建站电话?  laravel服务容器和依赖注入怎么理解_laravel服务容器与依赖注入解析  Win11怎么查看显卡温度 Win11任务管理器查看GPU温度【技巧】  网站优化排名时,需要考虑哪些问题呢?  Python并发异常传播_错误处理解析【教程】  Laravel如何记录日志_Laravel Logging系统配置与自定义日志通道  1688铺货到淘宝怎么操作 1688一键铺货到自己店铺详细步骤  昵图网官网入口 昵图网素材平台官方入口  手机网站制作与建设方案,手机网站如何建设?  Laravel如何理解并使用服务容器(Service Container)_Laravel依赖注入与容器绑定说明  如何有效防御Web建站篡改攻击?  JavaScript模板引擎Template.js使用详解  如何利用DOS批处理实现定时关机操作详解  深圳防火门网站制作公司,深圳中天明防火门怎么编码?  Laravel如何使用Scope本地作用域_Laravel模型常用查询逻辑封装技巧【手册】  如何快速启动建站代理加盟业务?  晋江文学城电脑版官网 晋江文学城网页版直接进入  无锡营销型网站制作公司,无锡网选车牌流程?  香港服务器部署网站为何提示未备案?  ChatGPT回答中断怎么办 引导AI继续输出完整内容的方法  香港服务器选型指南:免备案配置与高效建站方案解析  大学网站设计制作软件有哪些,如何将网站制作成自己app?  品牌网站制作公司有哪些,买正品品牌一般去哪个网站买?  Laravel如何使用Collections进行数据处理?(实用方法示例)  Laravel怎么集成Log日志记录_Laravel单文件与每日日志配置及自定义通道【详解】  谷歌浏览器如何更改浏览器主题 Google Chrome主题设置教程  宙斯浏览器怎么屏蔽图片浏览 节省手机流量使用设置方法  如何使用 Go 正则表达式精准提取括号内首个纯字母标识符(忽略数字与嵌套)  laravel怎么为应用开启和关闭维护模式_laravel应用维护模式开启与关闭方法  Laravel如何实现用户注册和登录?(Auth脚手架指南)  Laravel全局作用域是什么_Laravel Eloquent Global Scopes应用指南  EditPlus中的正则表达式 实战(2)  Laravel集合Collection怎么用_Laravel集合常用函数详解  瓜子二手车官方网站在线入口 瓜子二手车网页版官网通道入口  Win11怎么设置默认图片查看器_Windows11照片应用关联设置  linux写shell需要注意的问题(必看)  高防服务器租用指南:配置选择与快速部署攻略  b2c电商网站制作流程,b2c水平综合的电商平台?  Laravel Debugbar怎么安装_Laravel调试工具栏配置指南  详解Oracle修改字段类型方法总结  HTML透明颜色代码怎么让图片透明_给img元素加透明色的技巧【方法】  Laravel如何使用.env文件管理环境变量?(最佳实践)  东莞专业网站制作公司有哪些,东莞招聘网站哪个好?  Android实现代码画虚线边框背景效果  Laravel如何使用API Resources格式化JSON响应_Laravel数据资源封装与格式化输出  js实现获取鼠标当前的位置  浅谈redis在项目中的应用  矢量图网站制作软件,用千图网的一张矢量图做公司app首页,该网站并未说明版权等问题,这样做算不算侵权?应该如何解决?  Laravel Vite是做什么的_Laravel前端资源打包工具Vite配置与使用  如何选择可靠的免备案建站服务器?