1、异常捕获原则:将更精确的except语句放在前面 2、except 异常匹配是从上到下匹配,如果把父类异常类放在前面,则后面的异常永远不会触发 3、使用空raise:如果希望记录某个异常之后将它重新抛出交给上层处理,可使用不带参数的raise
常用写法
def incr_by_one(value: int):try:num = value + 1except (TypeError, ValueError) as e:print("发生错误了", e)raiseexcept Exception as e:print("Exception Error", e)else:print("这是没有抛出异常才会执行的")finally:print("调用finally ")return num# 这是没有抛出异常才会执行的# 调用finallyincr_by_one(value=1)# 发生错误了 must be str, not int# 调用finallyincr_by_one(value='2')
raise
def test_raise(num: int = 0):if num <= 0:raise Exception('num <= 0', num)else:print('num > 0')print("raise没有抛出异常,后面的代码正常执行")# num > 0# raise没有抛出异常,后面的代码正常执行test_raise(num=1)
通过上下文管理器忽略异常处理
"""忽略某个异常借使用上下文管理器的方式,实现可复用的「忽略异常」功能"""class IgnoreSomeException(object):def __enter__(self): ...def __exit__(self, exc_type, exc_value, traceback):print("exc_type=", exc_type, "exc_value=", exc_value, "traceback=", traceback)if exc_type == ZeroDivisionError:print('发现 ZeroDivisionError 异常, 跳过处理')# 返回True,则起到忽略异常的效果,返回False,则会将异常正常抛出return Trueprint("没发现 ZeroDivisionError 异常, 正常执行")return False# exc_type= <class 'ZeroDivisionError'> exc_value= division by zero traceback= <traceback object at 0x7f3192a816c8># 发现 ZeroDivisionError 异常, 跳过处理with IgnoreSomeException():1/0# exc_type= None exc_value= None traceback= None# 没发现 ZeroDivisionError 异常, 正常执行with IgnoreSomeException():1/1
通过contextmanager 处理异常
以 yield 关键字为界,yield之前的逻辑会在进入上下文管理器时执行(相当于enter) yield之后的逻辑会在退出上下文管理器时执行(相当于exit) 如果需要在上下文管理器内捕获异常,必须使用try语法块包裹yield语句
"""使用contextmanager装饰器 处理异常contextmanager 可将任意一个生成器函数直接转换为上下文管理器"""from contextlib import contextmanagerimport sys@contextmanagerdef ignore_exception_with_contextmanager():try:1/1yield Falseexcept ZeroDivisionError as e:print("ignore ZeroDivisionError :", sys.exc_info())finally:print("call finally func")# ignore ZeroDivisionError : (<class 'ZeroDivisionError'>, ZeroDivisionError('division by zero',), <traceback object at 0x7fc077b24c48>)# call finally funcwith ignore_exception_with_contextmanager():print(1/0)
