核心要点
掌握 try/except/else/finally 语义与执行顺序
能区分 Exception 层级并避免裸 except
知道 raise、自定义异常、with 与上下文管理器
标准回答
基本结构:
try:
risky()
except ValueError as e:
handle(e)
except (TypeError, KeyError):
handle_multi()
else:
on_success()
finally:
cleanup() # 必定执行最佳实践:
- 捕获具体异常,避免裸
except:吞掉 KeyboardInterrupt - 用
raise ... from e保留异常链 - 自定义异常继承
Exception,不要继承BaseException(除系统级) - 文件/锁/连接用
with open(...) as f:自动释放
工程场景:API 调用重试、数据管道脏数据跳过、训练中断保存 checkpoint。
常见误区
⚠️ 常见踩坑
裸 except: 或 except Exception 吞掉所有异常(连 KeyboardInterrupt、拼写错误导致的 NameError 也被静默),排障困难——应捕获具体类型。另一个坑:在 except 里用 raise NewError() 而非 raise NewError() from e,会丢失原始堆栈/异常链,看不到根因。
追问
追问 1:else 和 finally 分别在什么时候执行?
else 在 try 未抛异常时执行,常用于「成功路径」的收尾;finally 无论是否异常都会执行(除非进程被 kill),常用于释放资源。return 在 try 中也会先执行 finally 再真正返回。
追问 2:Exception 和 BaseException 有什么区别?
BaseException 是所有异常的根;Exception 是其子类,也是绝大多数业务异常的基类。KeyboardInterrupt、SystemExit、GeneratorExit 直接继承 BaseException 而非 Exception,故 except Exception 不会捕获它们——这正是让 Ctrl+C 能中断程序的原因。自定义异常应继承 Exception。
追问 3:如何用上下文管理器处理异常?
with 块会在退出(含异常)时调用对象的 __exit__(exc_type, exc_val, tb),可在此释放资源;__exit__ 返回 True 表示「已处理、吞掉异常」,返回 False/None 则异常继续向上抛。常用 contextlib.suppress(FileNotFoundError) 优雅忽略特定异常,或 @contextmanager 装饰生成器自定义 setup/teardown。
延伸学习
与本题相关的知识库文章、术语、工具与行业资讯。
📖 术语表
📰 AI 资讯