1. 错误和异常
1.1 错误
- 通常是使用不正确的语法造成的
1. # -*- coding: utf-8 -*- 2. # @Time : 2021/2/9 3. # @Author : 大海 4. 5. 6. # SyntaxError: invalid syntax 7. # if 后面缺少冒号(:) 8. a = 1 9. if a==1 10. print(a)
1.2 异常
- 当Python检测到一个错误时,解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的"异常"
1. # -*- coding: utf-8 -*- 2. # @Time : 2021/2/9 3. # @Author : 大海 4. 5. # ZeroDivisionError: division by zero 6. a = 10 / 0 7. print(a) 8. 9. 10. # TypeError: can only concatenate str (not "int") to str 11. b = '2' + 2 12. print(b)
2. 处理异常
2.1 try...except
- 把可能出现问题的代码,放在try中
- 把处理异常的代码,放在except中
try 语句的工作原理如下:
- 首先,执行 try 子句 (
try和except关键字之间的(多行)语句)。 - 如果没有异常发生,则跳过 except 子句 并完成
try语句的执行。 - 如果在执行 try 子句时发生了异常,则跳过该子句中剩下的部分。 然后,如果异常的类型和
except关键字后面的异常匹配,则执行 except 子句,然后继续执行try语句之后的代码。 - 如果发生的异常和 except 子句中指定的异常不匹配,则将其传递到外部的
try语句中;如果没有找到处理程序,则它是一个 未处理异常,执行将停止并显示如下所示的消息。
1. # -*- coding: utf-8 -*- 2. # @Time : 2021/2/9 3. # @Author : 大海 4. 5. try: 6. print('-----test--1---') 7. open('123.txt', 'r') 8. print('-----test--2---') 9. except IOError: 10. print('这是发生异常后处理的代码!')
2.2 except捕获多个异常
- 使用:把要捕获的异常的名字,放到except 后,并使用元组的方式仅进行存储
1. # -*- coding: utf-8 -*- 2. # @Time : 2021/2/9 3. # @Author : 大海 4. 5. try: 6. print('-----test--1---') 7. open('123.txt', 'r') # 如果123.txt文件不存在,那么会产生 IOError 异常 8. print('-----test--2---') 9. print(num) # 如果num变量没有定义,那么会产生 NameError 异常 10. 11. except (IOError, NameError): 12. print('这是发生异常后处理的代码!')
- 注:如果发生的异常和
except子句中的类是同一个类或者是它的基类,则异常和 except 子句中的类是兼容的(但反过来则不成立 --- 列出派生类的 except 子句与基类不兼容)
1. # -*- coding: utf-8 -*- 2. # @Time : 2021/2/9 3. # @Author : 大海 4. 5. class B(Exception): 6. pass 7. 8. 9. class C(B): 10. pass 11. 12. 13. class D(C): 14. pass 15. 16. 17. # 下面的代码将依次打印 B, B, B 18. for cls in [B, C, D]: 19. try: 20. raise cls() 21. except B: 22. print("B") 23. except C: 24. print("C") 25. except D: 26. print("D") 27. 28. # 下面的代码将依次打印 B, C, D 29. for cls in [B, C, D]: 30. try: 31. raise cls() 32. except D: 33. print("D") 34. except C: 35. print("C") 36. except B: 37. print("B")
2.3 捕获所有异常
1. # -*- coding: utf-8 -*- 2. # @Time : 2021/2/9 3. # @Author : 大海 4. 5. try: 6. 7. print(num) # 如果num变量没有定义,那么会产生 NameError 异常 8. 9. except Exception: 10. print('这是发生异常后处理的代码!')
2.4 获取异常信息
- 注:谨慎使用,因为以这种方式很容易掩盖真正的编程错误!它还可用于打印错误消息,然后重新引发异常
1. # -*- coding: utf-8 -*- 2. # @Time : 2021/2/9 3. # @Author : 大海 4. 5. try: 6. 7. print(num) # 如果num变量没有定义,那么会产生 NameError 异常 8. 9. except NameError as e: 10. print('这是发生异常后处理的代码!') 11. print(e) # 打印异常信息
2.5 else 子句
- 未发生异常时,执行else子句
1. # -*- coding: utf-8 -*- 2. # @Time : 2021/2/9 3. # @Author : 大海 4. 5. 6. try: 7. num = 100 8. print(num) 9. except NameError as e: 10. print('产生错误了:%s' % e) 11. else: 12. print('未发生异常时的逻辑代码')
2.6 finally 子句
- 不论
try语句是否产生了异常都会被执行
4种特殊情况:
- 如果在执行
try子句期间发生了异常,该异常可由一个except子句进行处理。 如果异常没有被某个except子句所处理,则该异常会在finally子句执行之后被重新引发。 - 异常也可能在
except或else子句执行期间发生。 同样地,该异常会在finally子句执行之后被重新引发。 - 如果在执行
try语句时遇到一个break,continue或return语句,则finally子句将在执行break,continue或return语句之前被执行。 - 如果
finally子句中包含一个return语句,则返回值将来自finally子句的某个return语句的返回值,而非来自try子句的return语句的返回值。
1. # -*- coding: utf-8 -*- 2. # @Time : 2021/2/9 3. # @Author : 大海 4. 5. 6. def divide(x, y): 7. try: 8. result = x / y 9. 10. except ZeroDivisionError: 11. print("division by zero!") 12. else: 13. print("result is", result) 14. finally: 15. print("executing finally clause") 16. 17. 18. divide(2, 1) 19. divide(2, 0) 20. 21. divide("2", "1")