这里介绍Python中的异常

自定义异常
Python中异常的基类为BaseException。其常见子类有:SystemExit、KeyboardInterrupt、Exception等。其中,Exception是常规异常的基类。当我们自定义异常类时,建议直接或间接继承Exception类。而不是直接继承BaseException
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| class CustomException(Exception): pass
class RuntimeException(ZeroDivisionError): pass
class BusinessException(Exception): def __init__(self, code, msg): super().__init__(self) self.code = code self.msg = msg
def __str__(self): detail = { "code": self.code, "msg": self.msg, } return str(detail) def get_code(self): return self.code def get_msg(self): return self.msg
if __name__ == "__main__": try: raise BusinessException(520, "参数校验失败") except BusinessException as ex: error_code = ex.get_code() error_msg = ex.get_msg() print(f"error code : {error_code}; error msg : {error_msg}") print("happen business exception:", ex) except Exception as ex: print("ex:", ex)
|

捕获异常
可以通过except子句捕获指定异常。具体地,可以在一个except子句中使用元组指定多个异常;也可以同时使用多个excpet子句
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| print("-------------- 捕获异常 -------------") try: num = 5/0 except ZeroDivisionError: print("[#1] 除数不能为0")
print("\n\n-------------- 捕获多个异常 -------------") for i in range(0,2) : try: if( i==1 ): i = "aaron" answer = 5 / i except (ZeroDivisionError, SyntaxError) as ex: print("Error: 除数为0, ex:", ex) except TypeError: print("发生语法错误") except : print("发生异常")
|

try-except的finally子句: 无论try中发生任何异常,finally中的代码都会被执行。即使try中发生的异常未被捕获,finally中代码在全部执行完成后,会再次重新抛出相应异常

抛异常
1. 基本语法
可通过raise子句来抛出异常
1 2
| raise AttributeError("用户姓名重复")
|

2. 异常捕获后继续抛该异常
捕获异常后,可直接使用raise,其会继续抛出当前捕获的异常
1 2 3 4 5 6
| try: num = 5/0 except ZeroDivisionError: print("[#1] 除数不能为0") raise
|

3. 异常捕获后抛其他异常
捕获异常后,可使用raise抛出其他的异常。此时,导致进入except子句的异常将被作为异常上下文存储起来,并出现在最终的错误消息中
1 2 3 4 5 6 7
| try: num = 5/0 except ZeroDivisionError: print("[#2] 除数不能为0") raise OSError
|

4. 异常捕获后抛其他异常,并重设异常上下文
捕获异常后,可使用raise抛出别的异常。同时,使用raise … from … 语句提供指定的异常上下文
1 2 3 4 5 6 7
| try: num = 5/0 except ZeroDivisionError: print("[#3] 除数不能为0") raise OSError from SyntaxError
|

5. 异常捕获后抛其他异常,并清除异常上下文
捕获异常后,可使用raise抛出别的异常。同时,使用raise … from None 语句 清除 异常上下文
1 2 3 4 5 6 7
| try: num = 5/0 except ZeroDivisionError: print("[#4] 除数不能为0") raise OSError from None
|

其他特性
else子句
try-except支持else子句。仅当try代码块成功执行,未抛出异常,才会执行else代码块
1 2 3 4 5 6 7 8
| for i in range(0,3) : try: print(f"i --->>> {i}") answer = 5 / i except ZeroDivisionError: print("[Error]: 除数i是0") else: print("answer:", answer)
|

try-with语句
try-with语句封装了try-except-finally 范式。使得对于需要关闭的资源,不再需要显式地通过finllay子句进行关闭
1 2 3 4 5 6
| with open("main.txt") as file1, open("readme.txt") as file2: src = file1.read(60)
print(f"文件file1是否被关闭: {file1.closed}") print(f"文件file2是否被关闭: {file2.closed}")
|

参考文献
- Python编程·第3版:从入门到实践 Eric Matthes著
- Python基础教程·第3版 Magnus Lie Hetland著
- 流畅的Python·第1版 Luciano Ramalho著