程序在运行过程中,如果出错就不会执行出错语句后面的代码,导致程序异常中断,因此为了提高程序健壮性,容错性,对容易发生错误的语句需要捕获异常对异常处理,保证程序的连续性提高稳定性。
def func_1():x = 10y = 0b = x/yprint(b)print("做完除法后需要执行的代码")Traceback (most recent call last):File "/Users/fujinjie/PythonProjects/develop_test/buyer_app_autotest/unit_test.py", line 30, in <module>r = func_1()File "/Users/fujinjie/PythonProjects/develop_test/buyer_app_autotest/unit_test.py", line 26, in func_1b = x/yZeroDivisionError: division by zero
由于y = 0 ,即除数为0,程序抛出:ZeroDivisionError: division by zero 的异常,b = x/y后面的代码并没有被继续执行,因为出错后程序是并不知道如何处理所以直接中断后续,并抛出错误告知用户,假设在我们自动化测试中,可能要执数百条用例,如果某一句子代码执行出现异常,则自动化程序就会异常中断无法继续执行测试。
一、try…except…错误处理机制
def func_1():x = 10y = 0try:b = x/yprint(b)except: # except捕获所有类型的异常,即只要有异常就捕获,不区分异常类型print("出现错误异常后,执行这里")print("做完除法后需要执行的代码")#出现错误异常后,执行这里做完除法后需要执行的代码
上面是通过try…except 优化后的函数,把会出错的代码放入try: 语句下作为try的子句,当try下面的代码出错时,程序会执行except:下面的代码,并执行程序后续代码,如果try: 下面的代码没有出错,则跳过except: 直接执行后续代码,程序继续运行。
在这里通过except我们捕获try代码块中的错误和异常,相当于告诉程序,当try下面语句出错时,该如何处理,上面我们直接做了一个字符串的输出: “出现错误异常后,执行这里”
二、except + 异常类型 捕获指定类型的异常
def func_1():x = 10y = 0try:b = x/yprint(b)except ZeroDivisionError as e: # as 为别名,当一个变量名称太长时可取别名代替简化print(f"出错啦,错误信息:{e}")print("做完除法后需要执行的代码")出错啦,错误信息:division by zero做完除法后需要执行的代码
通过traceback.format_exc()返回异常栈(返回是数据类型是字符串)
import tracebackdef func_1():x = 10y = 0try:b = x/yprint(b)except ZeroDivisionError as e: # as 为别名,当一个变量名称太长时可取别名代替简化ei = traceback.format_exc()print(f"出错啦,错误信息:{e},{ei}")print("做完除法后需要执行的代码")出错啦,错误信息:division by zero,Traceback (most recent call last):File "C:\Users\37210\Desktop\Jcmall_study\test_b\b_3.py", line 8, in func_1b = x/yZeroDivisionError: division by zero做完除法后需要执行的代码
常见异常举例
IOError 输入/输出异常;基本上是无法打开文件TypeError 传入对象类型与要求的不符合AttributeError 无法访问该对象,一般对象不存在,比如foo.x,但是foo没有属性xImportError 无法引入模块或包;基本上是路径问题或名称错误IndentationError 语法错误(的子类) ;代码没有正确对齐IndexError 下 标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]KeyError 试图访问字典里不存在的键NameError 使用一个还未被赋予对象的变量SyntaxError Python代码非法,一般是语法错误
except 后面可以指定捕获的错误类型,错误类型指定后,如果try:下面的代码抛出的错误类型非该指定的类型,则不会被捕获,程序仍旧会异常终止;
def func_1():x = 10y = 0try:b = x/yprint(b)except ValueError as e: # 这里对ValueError的异常进行捕获print(f"出错啦,错误信息:{e}")print("做完除法后需要执行的代码")Traceback (most recent call last):File "/Users/fujinjie/PythonProjects/develop_test/buyer_app_autotest/unit_test.py", line 33, in <module>r = func_1()File "/Users/fujinjie/PythonProjects/develop_test/buyer_app_autotest/unit_test.py", line 27, in func_1b = x/yZeroDivisionError: division by zero
三、except 捕获多个指定的错误类型
def func_1():x = 10y = 0try:b = x/yprint(b)except (TypeError,ValueError,ZeroDivisionError) as e: # 这里对 ZeroDivisionError的异常进行捕获print(f"出错啦,错误信息:{e}")print("做完除法后需要执行的代码")出错啦,错误信息:division by zero做完除法后需要执行的代码def func_1():x = 10y = "0" # 此处y是一个str类型try:b = x/yprint(b)except (TypeError,ValueError,ZeroDivisionError) as e: # 这里对 TypeError的异常进行捕获print(f"出错啦,错误信息:{e}")print("做完除法后需要执行的代码")出错啦,错误信息:unsupported operand type(s) for /: 'int' and 'str'做完除法后需要执行的代码
四、try…except…finally
不管try: 下面的语句是否报错异常,finally:下面的语句块始终会被执行
def func_1():x = 10y = 0try:b = x/yprint(b)except: # except捕获所有类型的异常,即只要有异常就捕获,不区分异常类型print("出现错误异常后,执行这里")finally:print("finally中代码始终会被执行")print("做完除法后需要执行的代码")出现错误异常后,执行这里finally中代码始终会被执行做完除法后需要执行的代码def func_2():x = 10y = 1try:b = x/yprint(b)except: # except捕获所有类型的异常,即只要有异常就捕获,不区分异常类型print("出现错误异常后,执行这里")finally:print("finally中代码始终会被执行")print("做完除法后需要执行的代码")10.0finally中代码始终会被执行做完除法后需要执行的代码
try: 下面的代码未发生异常,则执行else: 下面的代码,如果发生异常则执行except: 下面的代码,因此esle: 代码块的执行与否,取决于try: 下面是否报异常;
def func_1():x = 10y = 1try:b = x/yprint(b)except: # except捕获所有类型的异常,即只要有异常就捕获,不区分异常类型print("出现错误异常后,执行这里")else:print("没有异常会执行这里的代码")finally:print("finally中代码始终会被执行")print("做完除法后需要执行的代码")
