捕获具体异常比全局except更安全,因后者会吞掉KeyboardInterrupt等关键异常;raise...from保留异常链,自定义异常须继承Exception;finally中return会掩盖异常。

捕获特定异常比用 except: 全局兜底更安全
直接写 except: 看似省事,实际会吞掉 KeyboardInterrupt、SystemExit 甚至内存耗尽时的 MemoryError,导致程序无法被 Ctrl+C 中断或异常退出失效。
- 永远优先捕获具体异常类型,比如
except ValueError:、except FileNotFoundError: - 多个异常用元组写法:
except (ValueError, TypeError):,别写成except ValueError or TypeError:(后者逻辑错误) - 想兜底又不破坏中断信号?加一句
except BaseException:太重,改用except Exception:——它不包含SystemExit和KeyboardInterrupt
raise 和 raise ... from 的区别不能只看语法
抛异常不只是“让程序停”,关键是传递上下文。直接 raise 会丢失原始异常栈,而 raise ... from 能保留因果链,对排查嵌套调用里的问题至关重要。
- 在 except 块里想包装异常并透出原因:用
raise NewError("xxx") from original_exc - 如果只是重新抛出当前异常(比如做清理后继续上报),直接写
raise即可,不用from - 误写
raise exc from None会显式切断异常链,除非你明确要隐藏源头,否则别这么干
自定义异常类必须继承 Exception 或其子类
Python 不会把普通 class 当作异常处理。哪怕名字叫 MyError,没继承 Exception 就没法被 except MyError: 捕获。
- 最简写法:
class ValidationError(Exception): pass - 想带额外字段(比如错误码)?在
__init__里存,别覆盖__str__除非真有格式化需求 - 避免继承
BaseException——那是给系统级异常(如SystemExit)留的,业务异常走Exception分支
finally 里 return 会吃掉异常
这是最容易踩的坑:只要 finally 块里有 return 或 raise,无论 try 或 except 里发生了什么,最终都以 finally 的行为为准。
立即学习“Python免费学习笔记(深入)”;
- 示例:
try: raise ValueError() finally: return 42→ 函数返回42,ValueError彻底消失 - 需要确保资源释放但不想干扰异常传播?
finally里只做清理(如file.close()),别写return或raise - 真要在
finally抛新异常?先用sys.exc_info()判断是否有活跃异常,再决定是否覆盖
finally 的控制权优先级,这三块组合起来就容易出意料之外的行为。写的时候多想想“这个 except 真能抓到我要的错吗”“这个 finally 会不会悄悄吞掉报错”。










