应捕获具体异常类型而非裸except,避免吞掉系统异常;合理使用else和finally分离成功逻辑与资源清理;用raise from保留异常链;自定义异常继承Exception并命名带Error后缀。

捕获特定异常类型而不是裸 except
裸 except: 会吞掉所有异常,包括 KeyboardInterrupt 和 SystemExit,导致程序无法被 Ctrl+C 中断,调试时也看不到真实错误。必须明确写出要处理的异常类。
- 正确写法是
except ValueError:、except FileNotFoundError:等具体类型 - 多个异常可用元组形式:
except (ValueError, TypeError): - 不要用
except Exception:代替具体类型——它仍会捕获本不该拦截的系统级异常 - 如果真需要兜底,应放在具体
except块之后,并加上日志记录,例如:except ValueError as e: print(f"输入格式错误: {e}") except Exception as e: logging.error("未预期异常", exc_info=True) raise
区分 try except else finally 的职责
else 块只在 try 中没抛异常时执行,适合放不希望被异常捕获的“成功路径”逻辑;finally 一定执行,适合清理资源,但它不能替代 else 来隔离副作用。
-
else中的代码不会被当前except捕获——如果它自己出错,就真的抛出去 -
finally里不要return或raise,否则会吃掉try或else中的异常或返回值 - 常见误用:
try里打开文件,except处理失败,但忘记在finally里检查file是否定义就调用file.close()—— 应改用with语句,或在try前初始化变量
异常链与 raise from 的使用场景
当你要把底层异常包装成业务异常并保留原始上下文时,用 raise NewException(...) from original_exc;若只是简单重抛,直接用 raise(不带参数),它会自动延续原异常链。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
-
raise ValueError("配置加载失败") from e会让 traceback 同时显示原始异常和新异常,方便定位 - 避免
raise ValueError("配置加载失败")+except后再raise—— 这样会丢失原始异常信息 - 在日志中打印异常时,用
traceback.format_exception(type(e), e, e.__traceback__)才能完整输出链式 traceback
自定义异常该继承哪个基类
业务异常应继承 Exception,而非 BaseException;绝不要继承 SystemExit、KeyboardInterrupt 等系统退出类,否则可能干扰程序生命周期。
- 命名建议带
Error后缀,如PaymentValidationError,符合 Python 社区惯例 - 构造函数里可以接受额外字段,比如
self.code = code,方便上层做差异化处理 - 如果多个模块共用一套错误码,别把状态码硬编码在异常类里——应通过参数传入,保持类职责单一
实际中最容易被忽略的是:异常类型匹配是精确的,父类异常不会被子类 except 块捕获,反过来才成立。比如 except OSError: 能抓到 FileNotFoundError,但 except FileNotFoundError: 抓不到 OSError。这点在跨平台处理文件操作时特别容易踩坑。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










