python错误分exception(可捕获)和baseexception非exception子类(如systemexit、keyboardinterrupt,不应被常规except捕获);自定义异常须继承exception;错误码非python惯例,推荐用异常类型区分;异常应含类型、上下文、安全可打印信息;异常用于意外情况,非预期分支。

Python 中的错误类型到底怎么分?
Python 的错误分两大类:Exception(可捕获)和 BaseException 子类中非 Exception 的(一般不该捕获)。你日常写的 try...except 默认只抓 Exception 及其子类,比如 ValueError、TypeError、KeyError。
-
SystemExit、KeyboardInterrupt、GeneratorExit都是BaseException的直系子类,绕过except Exception: - 写日志或兜底逻辑时若用了
except:(空 except),会意外吞掉KeyboardInterrupt,导致 Ctrl+C 失效 - 自定义异常务必继承
Exception,别直接继承BaseException,否则可能被顶层异常处理器跳过
try:
sys.exit(1)
except Exception:
print("这行不会执行") # 确实不会
except SystemExit:
print("得显式写这里才能捕获")错误码在 Python 里有没有标准用法?
Python 标准库几乎不依赖错误码——它靠异常类型和消息区分问题。比如 os.open() 抛 OSError,但具体是权限不足还是文件不存在,得看 .errno 属性,而不是返回一个整数码。
-
OSError.errno是 POSIX 错误码(如errno.EACCES= 13),跨平台但语义弱 -
OSError.strerror是可读描述,更适合用户提示 - 第三方库(如 Flask、FastAPI)通常不用错误码,而是用 HTTP 状态码 + JSON 错误体,和 Python 异常解耦
别在业务逻辑里自己定义 ERROR_USER_NOT_FOUND = 40401 这种码——它既没被标准支持,又增加调用方理解成本。真要区分场景,用不同异常类更直接:
class UserNotFoundError(Exception): pass class UserLockedError(Exception): pass
自定义异常该带哪些信息?
一个有用的自定义异常至少包含三样东西:类型明确、上下文可查、能安全打印。
立即学习“Python免费学习笔记(深入)”;
使用模板与程序分离的方式构建,依靠专门设计的数据库操作类实现数据库存取,具有专有错误处理模块,通过 Email 实时报告数据库错误,除具有满足购物需要的全部功能外,成新商城购物系统还对购物系统体系做了丰富的扩展,全新设计的搜索功能,自定义成新商城购物系统代码功能代码已经全面优化,杜绝SQL注入漏洞前台测试用户名:admin密码:admin888后台管理员名:admin密码:admin888
- 必须继承
Exception(不是BaseException) - 构造时接收关键参数(如
user_id、file_path),存为实例属性,别只拼进message字符串里 - 重写
<strong>str</strong>或用<strong>init</strong>中的super().<strong>init</strong>(...)确保日志能打出来 - 避免在异常消息里拼接敏感数据(如密码、token),哪怕只是调试用
常见反例:
raise Exception(f"Failed to load config for {secret_token}") # 危险
# 正确写法:
raise ConfigLoadError(user_id=user_id, config_name=name) # 属性化,不泄露什么时候该抛异常,什么时候该返回 None 或 False?
Python 社区共识很清晰:异常用于“意外”情况,而非“预期分支”。
-
dict.get(key)返回None是设计使然,因为 key 不存在是常见预期路径 -
dict[key]抛KeyError是因为访问缺失 key 被视为逻辑错误或配置缺失 - 文件操作中,
os.path.exists()+open()是竞态风险,不如直接try...open()...except FileNotFoundError - API 函数如果调用方需要频繁判断失败原因(比如重试策略依赖错误类型),就该抛异常;如果只是“有/无结果”,返回
None更轻量
容易踩的坑:
- 把网络超时、数据库连接失败这种外部不确定性当“正常返回值”处理,结果重试逻辑散落在各处
- 在工具函数里用
print("warning: ...")代替异常,导致上游无法感知失败 - 为省事把所有错误都转成
RuntimeError,丢失原始类型和上下文
异常机制不是摆设,它是 Python 控制流的一部分。用错地方,后期加监控、做分级告警、写测试都会变麻烦。









