except Exception 是危险的兜底写法,因为它会吞掉 KeyboardInterrupt、SystemExit 等不应捕获的异常,掩盖错误、中断调试、导致资源泄漏;应按文档捕获具体异常如 json.JSONDecodeError,并用工具如 pylint、bandit 检测宽泛捕获。

为什么except Exception是危险的兜底写法
它会吞掉所有异常,包括你本不该捕获的 KeyboardInterrupt、SystemExit,甚至 MemoryError。程序看似“不崩溃”,实则掩盖逻辑错误、中断调试信号、导致资源泄漏——比如按 Ctrl+C 时程序无响应,或子进程残留。
应该捕获哪些具体异常?看调用栈和文档
不要靠猜,直接查你调用的函数可能抛出什么异常。比如 json.loads() 明确文档里写会抛 json.JSONDecodeError,open() 可能抛 FileNotFoundError 或 PermissionError。实际写法示例:
try:
data = json.loads(text)
except json.JSONDecodeError as e:
logger.error(f"JSON parse failed: {e}")
return None
常见误区:
- 用
except ValueError捕json.loads()—— Python 3.5+ 已改用更具体的json.JSONDecodeError - 用
except IOError捕文件操作 —— 现代 Python 中应优先用FileNotFoundError、PermissionError等子类 - 把多个不相关的异常塞进一个
except (A, B, C)—— 它们处理逻辑不同,就该分开写
如何定位代码里隐藏的宽泛异常捕获?
用静态检查工具快速扫描:
立即学习“Python免费学习笔记(深入)”;
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
-
pylint配置dangerous-default-except规则(默认启用),会标出except Exception和空except: -
bandit运行bandit -r . --skip B110(B110 是空 except 检查) - IDE 如 PyCharm,在
except Exception下会有黄色波浪线提示 “Too broad exception clause”
注意:有些框架(如 Flask 的全局 error handler)确实需要捕 Exception,但那是顶层兜底,不是业务逻辑里随手写的。
真需要兜底时,怎么写才安全?
如果必须做顶层异常拦截(比如服务入口),至少排除系统级中断信号:
try:
main()
except (KeyboardInterrupt, SystemExit):
raise # 让 Ctrl+C 和 os._exit() 正常生效
except Exception:
log_exception()
exit(1)
更稳妥的做法是显式列出你预期可能漏掉的业务异常,而不是依赖 Exception。真正难预料的,往往是 AttributeError(属性不存在)、TypeError(类型错)这类——它们往往暴露的是代码缺陷,不该被静默吃掉。
最常被忽略的点:日志里没记录 exc_info=True,导致堆栈丢失;或者在 except 块里又抛新异常却没带原 traceback,用 raise new_exc from e 才能保留上下文。

















