一、基础知识
1、一个try
语句支持多个except
子句,但请记得将更精确的异常类型放在前面。
2、try
语句的else
分支会在没有异常时执行,因此它可以用来替代标记变量(flag变量)。
3、不带任何参数的raise
语句会直接重复抛出当前异常。
4、上下文管理器经常用来处理异常,它最常见的用途是替代finally
子句。
5、上下文管理器可以用来忽略某段代码里的异常(不影响功能正常执行逻辑的异常)。
6、使用@contextmanager
装饰器可以轻松定义上下文管理器。
二、错误处理与参数校验
1、当你可以选择编写条件判断或者异常捕获时,优先选用异常捕获(EAFP)
EAFP,Easier to Ask for Forgiveness than Permission,获取原谅比许可简单。
与之相对应的是LBYL,Look Before You Leap,三思而后行。
Python社区更偏爱基于异常捕获的EAFP风格,通俗点说,开发者们对待下雨——“吃感冒药”胜过“看看天气预报”。
2、不要让函数返回错误信息,直接抛出自定义异常吧。
3、手动校验数据合法性非常繁琐,尽量使用专业模块来做这件事(例如pydantic
)。
4、不要使用assert
来作为参数校验,请使用raise来替代它。
5、处理错误需要付出额外的成本,加入能够通过设计来避免就再好不过了。
6、在设计API时,需要慎重考虑是否真的有必要抛出错误。
7、使用“空对象模式”能免去一些针对边界情况的错误处理工作。
三、当捕获异常时
1、过于模糊和宽泛的异常捕获可能会让成语便于崩溃,但更有可能带来更大的麻烦。
2、异常捕获贵在精确,只捕获可能抛出异常的语句,值捕获可能的异常类型。
3、有时候,让程序提早崩溃未必是什么坏事。
4、完全忽略异常是风险非常高的行为,大多数情况下,请至少记录一条错误日志信息。
四、当抛出异常时
1、保证模块内抛出的异常与模块自身的抽象级别一致。
2、如果异常的抽象级别过高,把它替换为更低级的新异常。
3、如果异常的抽象级别过低,把它包装为更高级的新异常,然后重新抛出。
4、不要让调用方用字符串匹配来判断异常种类,尽量提供可区分的异常。
参考内容:《Python工匠——案例、技巧与工程实践》