1、异常捕获原则:将更精确的except语句放在前面 2、except 异常匹配是从上到下匹配,如果把父类异常类放在前面,则后面的异常永远不会触发 3、使用空raise:如果希望记录某个异常之后将它重新抛出交给上层处理,可使用不带参数的raise

常用写法

  1. def incr_by_one(value: int):
  2. try:
  3. num = value + 1
  4. except (TypeError, ValueError) as e:
  5. print("发生错误了", e)
  6. raise
  7. except Exception as e:
  8. print("Exception Error", e)
  9. else:
  10. print("这是没有抛出异常才会执行的")
  11. finally:
  12. print("调用finally ")
  13. return num
  14. # 这是没有抛出异常才会执行的
  15. # 调用finally
  16. incr_by_one(value=1)
  17. # 发生错误了 must be str, not int
  18. # 调用finally
  19. incr_by_one(value='2')

raise

  1. def test_raise(num: int = 0):
  2. if num <= 0:
  3. raise Exception('num <= 0', num)
  4. else:
  5. print('num > 0')
  6. print("raise没有抛出异常,后面的代码正常执行")
  7. # num > 0
  8. # raise没有抛出异常,后面的代码正常执行
  9. test_raise(num=1)

通过上下文管理器忽略异常处理

  1. """忽略某个异常
  2. 借使用上下文管理器的方式,实现可复用的「忽略异常」功能
  3. """
  4. class IgnoreSomeException(object):
  5. def __enter__(self): ...
  6. def __exit__(self, exc_type, exc_value, traceback):
  7. print("exc_type=", exc_type, "exc_value=", exc_value, "traceback=", traceback)
  8. if exc_type == ZeroDivisionError:
  9. print('发现 ZeroDivisionError 异常, 跳过处理')
  10. # 返回True,则起到忽略异常的效果,返回False,则会将异常正常抛出
  11. return True
  12. print("没发现 ZeroDivisionError 异常, 正常执行")
  13. return False
  14. # exc_type= <class 'ZeroDivisionError'> exc_value= division by zero traceback= <traceback object at 0x7f3192a816c8>
  15. # 发现 ZeroDivisionError 异常, 跳过处理
  16. with IgnoreSomeException():
  17. 1/0
  18. # exc_type= None exc_value= None traceback= None
  19. # 没发现 ZeroDivisionError 异常, 正常执行
  20. with IgnoreSomeException():
  21. 1/1

通过contextmanager 处理异常

以 yield 关键字为界,yield之前的逻辑会在进入上下文管理器时执行(相当于enter) yield之后的逻辑会在退出上下文管理器时执行(相当于exit) 如果需要在上下文管理器内捕获异常,必须使用try语法块包裹yield语句

  1. """
  2. 使用contextmanager装饰器 处理异常
  3. contextmanager 可将任意一个生成器函数直接转换为上下文管理器
  4. """
  5. from contextlib import contextmanager
  6. import sys
  7. @contextmanager
  8. def ignore_exception_with_contextmanager():
  9. try:
  10. 1/1
  11. yield False
  12. except ZeroDivisionError as e:
  13. print("ignore ZeroDivisionError :", sys.exc_info())
  14. finally:
  15. print("call finally func")
  16. # ignore ZeroDivisionError : (<class 'ZeroDivisionError'>, ZeroDivisionError('division by zero',), <traceback object at 0x7fc077b24c48>)
  17. # call finally func
  18. with ignore_exception_with_contextmanager():
  19. print(1/0)