except: 最危险,因会捕获 KeyboardInterrupt、SystemExit 等致命异常,并掩盖 NameError 等 bug;应使用具体异常类型或 except Exception:,避免吞错、耦合逻辑、滥用控制流。

为什么 except: 是最危险的异常捕获写法
它会吞掉 KeyboardInterrupt、SystemExit,甚至你手动按 Ctrl+C 都无法中断程序。更糟的是,它还会掩盖真正的 bug——比如变量名拼错引发的 NameError,结果程序看似“正常运行”,实则逻辑已错位。
- 永远用具体异常类型,比如
except ValueError:或except FileNotFoundError: - 不确定时宁可不捕获,让异常冒泡;Python 的 traceback 已经足够定位问题
- 真要兜底,至少写成
except Exception:,避开BaseException子类(如SystemExit)
把业务逻辑塞进 except 块的后果
常见于“文件不存在就创建默认配置”这类场景——看着省事,实际把错误处理和初始化逻辑耦合在一起,后续想单独测试默认配置生成逻辑,就得 mock 异常,路径变复杂。
- 把恢复逻辑抽成独立函数,比如
create_default_config(),在except里只调用它 - 异常块里只做三件事:记录日志、清理资源(如关闭文件)、抛出新异常或返回 fallback 值
- 如果 fallback 行为本身可能失败(比如写入临时文件也失败),别再套一层
try/except,而是让上层决定怎么降级
raise 和 raise ... from 的区别不是语法糖
直接写 raise ValueError("配置加载失败") 会丢掉原始异常的堆栈,调试时只能看到最后一行,找不到是哪个 json.loads() 出的问题。
- 用
raise ValueError("配置加载失败") from e保留原始异常链,Python 3.7+ 默认显示两层 traceback - 如果想完全替换异常(比如隐藏敏感路径),用
raise NewError(...) from None,但得确保上层能理解这个新异常的语义 - 避免在
except块里只写raise(无参数),它虽保留原异常,但容易让人误以为是意外重抛,而不是有意转译
自定义异常该继承 Exception 还是 RuntimeError
继承 RuntimeError 是错的——它是为“运行时无法归类的错误”保留的,比如解释器内部状态混乱。业务异常必须继承 Exception,否则会被 except Exception: 漏掉(因为 RuntimeError 是 Exception 的子类,但语义不符)。
程序介绍:程序采用.net 2.0进行开发,全自动应用淘客api,自动采集信息,无需,手工更新,源码完全开放。(程序改进 无需填入阿里妈妈淘客API 您只要修改app_code文件下的config.cs文件中的id为你的淘客id即可)针对淘客3/300毫秒的查询限制,系统采用相应的解决方案,可以解决大部分因此限制带来的问题;程序采用全局异常,避免偶尔没考虑到的异常带来的问题;程序源码全部开放,请使
立即学习“Python免费学习笔记(深入)”;
- 所有自定义异常统一继承
Exception,命名以Error结尾,比如ConfigLoadError - 如果需要分组捕获,再加一层基类,比如
class AppError(Exception): pass,然后让具体异常继承它 - 不要为了“看起来高级”而嵌套多层继承,三层以上就难维护;异常类型够用就行,靠消息字段传递细节比靠类型区分更灵活
异常不是控制流替代品,也不是日志代理。写 except 前先问一句:这个错误发生后,调用方真的有合理策略应对吗?没有的话,让它崩,比静默错更可靠。





