程序在运行过程中,难免会遇到错误,有的是编写人员疏忽造成的语法错误,有的是程序内部隐含逻辑问题造成的数据错误,还有的是程序运行时与系统的规则冲突造成的系统错误,等等。如果出错就不会执行出错语句后面的代码,导致程序异常中断,因此为了提高程序健壮性,容错性,对容易发生错误的语句需要捕获异常对异常处理,保证程序的连续性提高稳定性。
def get_num(l:list, n1:int, n2:int):
print('执行get_num函数')
num1 = l[n1]
num2 = l[n2]
res = num1/num2
return res
def func_1():
print('执行func_1函数')
def func_2():
print('执行func_2函数')
get_num([1,2,3,4],5)
func_1()
func_2()
上述代码在调用函数get_num时会抛出indexError的异常,导致程序中断?
def func_1():
x = 10
y = 0
b = x/y
print(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_1
b = x/y
ZeroDivisionError: division by zero
由于y = 0 ,即除数为0,程序抛出:ZeroDivisionError: division by zero 的异常,b = x/y后面的代码并没有被继续执行,因为出错后程序是并不知道如何处理所以直接中断后续,并抛出错误告知用户,假设在我们自动化测试中,可能要执数百条用例,如果某一句子代码执行出现异常,则自动化程序就会异常中断无法继续执行测试。
当一个程序发生异常时,代表该程序在执行时出现了非正常的情况,无法再执行下去。默认情况下,程序是要终止的。如果要避免程序退出,可以使用捕获异常的方式获取这个异常的名称,再通过其他的逻辑代码让程序继续运行,这种根据异常做出的逻辑处理叫作异常处理。异常处理不仅仅能够管理正常的流程运行,还能够在程序出错时对程序进行必要的处理。大大提高了程序的健壮性和人机交互的友好性。
一、try...except...异常处理机制
def func_1():
x = 10
y = 0
try:
b = x/y
print(b)
except: # except捕获所有类型的异常,即只要有异常就捕获,不区分异常类型
print("出现错误异常后,执行这里")
print("做完除法后需要执行的代码")
#出现错误异常后,执行这里
做完除法后需要执行的代码
上面是通过try...except 优化后的函数,把会出错的代码放入try: 语句下作为try的子句,当try下面的代码出错时,程序会执行except:下面的代码,并执行程序后续代码,如果try: 下面的代码没有出错,则跳过except: 直接执行后续代码,程序继续运行。
在这里通过except我们捕获try代码块中的错误和异常,相当于告诉程序,当try下面语句出错时,该如何处理,上面我们直接做了一个字符串的输出: "出现错误异常后,执行这里"
二、except + 异常类型 捕获指定类型的异常
def func_1():
x = 10
y = 0
try:
b = x/y
print(b)
except ZeroDivisionError as e: # as 为别名,当一个变量名称太长时可取别名代替简化
print(f"出错啦,错误信息:{e}")
print("做完除法后需要执行的代码")
出错啦,错误信息:division by zero
做完除法后需要执行的代码
基本语法构成
try:
可能产生异常的代码块
except [ (Error1, Error2, ... ) [as e] ]:
处理异常的代码块1
except [ (Error3, Error4, ... ) [as e] ]:
处理异常的代码块2
except [Exception]:
处理其它异常
该格式中,[] 括起来的部分可以使用,也可以省略。其中各部分的含义如下:
try except 语句的执行流程如下:
首先执行 try 中的代码块,如果执行过程中出现异常,系统会自动生成一个异常类型,并将该异常提交给 Python 解释器,此过程称为。
捕获异常
当 Python 解释器收到异常对象时,会寻找能处理该异常对象的 except 块,如果找到合适的 except 块,则把该异常对象交给该 except 块处理,这个过程被称为处理异常。如果 Python 解释器找不到处理异常的 except 块,则程序运行终止,Python 解释器也将退出。
很多时间我们并不知道try下面包裹的子句会出现何种类型的异常,对于这种情况我们一般交给 Exception来处理,即表示可以接收任何类型的异常
?
try:
#...
except Exception:
#...
一个简的例子
try:
num_1 = int(input("输入一个整数:"))
num_2 = int(input("输入另一个整数:"))
print( num_1/num_2 )
except ValueError:
print("数值错误:程序只能接收整数参数")
except ArithmeticError:
print("算术错误")
except Exception:
print("未知异常")
该程序中,根据用户输入num_1 和 num_2 值的不同,可能会导致 ValueError、ArithmeticError 异常:
通过traceback.format_exc()返回异常栈(返回是数据类型是字符串)
?
import traceback
def func_1():
x = 10
y = 0
try:
b = x/y
print(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_1
b = x/y
ZeroDivisionError: division by zero
做完除法后需要执行的代码
?常见异常举例
IOError 输入/输出异常;基本上是无法打开文件
TypeError 传入对象类型与要求的不符合
AttributeError 无法访问该对象,一般对象不存在,比如foo.x,但是foo没有属性x
ImportError? 无法引入模块或包;基本上是路径问题或名称错误
IndentationError? 语法错误(的子类) ;代码没有正确对齐
IndexError? 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError? 试图访问字典里不存在的键
NameError? 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,一般是语法错误
except 后面可以指定捕获的错误类型,错误类型指定后,如果try:下面的代码抛出的错误类型非该指定的类型,则不会被捕获,程序仍旧会异常终止;?
?
def func_1():
x = 10
y = 0
try:
b = x/y
print(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_1
b = x/y
ZeroDivisionError: division by zero
三、except 捕获多个指定的错误类型?
def func_1():
x = 10
y = 0
try:
b = x/y
print(b)
except (TypeError,ValueError,ZeroDivisionError) as e: # 这里对 ZeroDivisionError的异常进行捕获
print(f"出错啦,错误信息:{e}")
print("做完除法后需要执行的代码")
出错啦,错误信息:division by zero
做完除法后需要执行的代码
def func_1():
x = 10
y = "0" # 此处y是一个str类型
try:
b = x/y
print(b)
except (TypeError,ValueError,ZeroDivisionError) as e: # 这里对 TypeError的异常进行捕获
print(f"出错啦,错误信息:{e}")
print("做完除法后需要执行的代码")
出错啦,错误信息:unsupported operand type(s) for /: 'int' and 'str'
做完除法后需要执行的代码
四、try...except...finally
Python异常处理机制还提供了一个?finally?语句,通常用来为 try 块中的程序做扫尾清理工作
注意:finally 只要求和 try 搭配使用,而至于该结构中是否包含 except ,对于 finally 不是必须的
finally 语句的功能是:无论 try 块是否发生异常,最终都要进入 finally 语句,并执行其中的代码块。
def func_1():
x = 10
y = 0
try:
b = x/y
print(b)
finally:
print("无论try中代码是不出现异常,finally中代码始终会被执行")
print("继续执行模块中其他代码")
def func_2():
x = 10
y = 1
try:
b = x/y
print(b)
finally:
print("无论try中代码是不出现异常,finally中代码始终会被执行")
print("继续执行模块中其他代码")
比较上面两个函数 func_1与func_2,func_1中的try代码块会出现异常,func_2中的try代码块未出现异常,但两个函数的finally包裹的子句都得到了执行
五、try...except...else
在原本的
try except
结构的基础上,Python异常处理机制还提供了一个 else 块,也就是原有 try except 语句的基础上再添加一个 else 块,即
try:
#...
except:
#...
else:
#...
使用 else 包裹的代码,只有当 try 块没有捕获到任何异常时,才会得到执行;反之,如果 try 块捕获到异常,即便调用对应的 except 处理完异常,else 块中的代码也不会得到执行。
注意:else 必须和 try except 搭配使用
?
try:
result = 20 / int(input('请输入除数:'))
print(result)
except ValueError:
print('必须输入整数')
except ArithmeticError:
print('算术错误,除数不能为 0')
else:
print('没有出现异常')
print("继续执行")
try: 下面的代码未发生异常,则执行else: 下面的代码,如果发生异常则执行except: 下面的代码,因此esle: 代码块的执行与否,取决于try: 是否报异常;?
def func_1():
x = 10
y = 1
try:
b = x/y
print(b)
except: # except捕获所有类型的异常,即只要有异常就捕获,不区分异常类型
print("出现错误异常后,执行这里")
else:
print("没有异常会执行这里的代码")
finally:
print("finally中代码始终会被执行")
print("做完除法后需要执行的代码")
总结一个
Python异常处理语法结构如下
try:
#业务实现代码
except Exception1 as e:
#捕获到Exception1异常后执行此代码
...
except Exception2 as e:
#捕获到Exception2异常后执行此代码
...
#可以有多个 except
...
else:
#try中未出现异常是执行此处代码,有异常时不会执行
finally :
#不管try中代码是否出现异常,此处代码始终会执行
...
注:finally必须跟try连用,跟except与else无连用关系;else必须跟try...except...连用
即整个结构try是必须存在的
异常处理执行过程
?
练习:
1、下面代码存在keyError异常,请通过try...except捕获并处理该异常,当错误时print输出“输入的key不存在,请检查key”
goods_inf = {'Id': 10001, 'goods': 'JBL小音响', 'price': 501}
def get_goods_inf(goods:dict, key:str):
res = goods[key]
return res
get_goods_inf(goods=goods_inf, key='id')
2、请优化下面函数,当除数为0时捕获异常并告知用户除数不能为0,当输入的是非数字时捕获异常并提示用户输入的是非数字字符?
def add_num():
num1 = int(input('请输入被除数:'))
num2 = int(input('请输入除数:'))
res = num1/num2
return res
?
3、基于add_num函数,请通过try...except...else优化,当未捕获到异常是函数返回res,当捕获到异常时函数一律返回”输入错误,请检查输入并把这个异常类型打印出来“
4、基于add_num函数,请通过finally进行优化,函数始终会通过print输出’add_num函数执行完毕’
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?