异常及其处理
1.1 异常的简介
1 程序在运行过程中不可避免会出现一些错误这些错误在程序中我们就称之为异常
程序在运行过程中,一旦出现异常会导致程序立即终止 异常后面的代码都不会执行
2 处理异常
程序出现异常,目的并不是要程序立即终止,而是希望在出现异常时,我们可以编写代码对异常进行处理
3 语法:
try语句
try:
代码块(可能会出现错误的语句)
except 异常类型 as异常名:
代码块(出现错误以后的处理方式)
except 异常类型 as异常名:
代码块(出现错误以后的处理方式)
except 异常类型 as异常名:
代码块(出现错误以后的处理方式)
…
else:
代码块(没有错误时要执行的语句)
finally:
代码块(是否有异常都会执行)
下面举例来说明一下
try:
print(b)# 注意这里并没有被定义,所以系统会报错,错误类型为 NameError
a = 9/0 # 由于除以0,所以错误类型为 ZeroDivisionError
b = 9/3 # 没有错误
except NameError as e1:# 将异常类型赋值给变量e1,可以在except中调用
print('出错啦')
except ZeroDivisionError as e2: # 将异常类型赋值给变量e2,可以在except中调用
print('除数为0')
else:
print('没出错')
finally:
print('是否有异常都执行错都执行')
当执行print(b)时结果为,或者try中三条语句一起执行时
出错啦
是否有异常都执行错都执行
当执行9/0时结果为
除数为0
是否有异常都执行错都执行
当执行9/3时,结果为
没出错
是否有异常都执行错都执行
总结一下
try except 语句的执行流程如下:
1 首先执行 try 中的代码块,如果执行过程中出现异常,系统会自动生成一个异常对象,该异常对象会提交给 Python 解释器,此过程被称为引发异常。
2 当 Python 解释器收到异常对象时,会寻找能处理该异常对象的 except 块,如果找到合适的 except 块,则把该异常对象交给该 except 块处理,
这个过程被称为捕获异常。如果 Python 解释器找不到捕获异常的 except 块,则程序运行终止,Python 解释器也将退出
3 如果try块被执行一次,则只有一个except会被执行
上述代码还可以写为
try:
print(b)
a = 9/0
b = 9/3
except (NameError,ZeroDivisionError):
print('出错啦')
except :
print('其他错误类型')
else:
print('没出错')
finally:
print('是否有异常都执行错都执行')
运行结果
出错啦
是否有异常都执行错都执行
异常的传播
1 当在函数中出现异常时,如果在函数中对异常进行了处理,则异常不会再传播,
如果函数中没有对异常进行处理,则异常会继续像函数调用处传播
如果函数调用处处理了异常,则不再传播,如果没有处理则继续像调用处传播
直到传递到全局作用域,如果依然没有处理,则程序终止,并且显示异常信息
下面举出例子,具体解释
def fn():
print('hello.........')
print(9 / 0) # 1
fn() # 2
错误从1处传播到了2处
下面使用try进行处理
def fn():
print('hello.........')
print(9 / 0)
try:
fn()
except:
pass
# 运行结果
hello.........
2 当程序运行过程中出现异常以后,所有的异常信息会被专门保存到一个异常对象当中,而异常传播时,实际上就是异常对象抛给了调用处
例如下面这段代码
def fn():
print('hello fn')
print(20 / 0) # 设置错误
def fn2():
print('hello fn2')
fn()# 在函数fn2中调用fn()
print('hello fn3')
def fn3():
fn2() # 在函数fn3中调用fn2()
fn3()
1.3 异常对象
如果except后面不跟任何内容,则此时会捕获到所有的异常,如果except后面跟着一个异常类型,那么此时它只会捕获该类型的异常
下面举例具体说明一下
print('异常出现前')
lst = []
try:
lst[10]# 3 IndexError 错误类型
except NameError:
# 如果except后面不跟任何内容,则此时会捕获到所有的异常
# 如果except后面跟着一个异常类型,那么此时它只会捕获该类型的异常
# print('处理异常的逻辑..')
print('出现 NameError 异常')
except ZeroDivisionError:
print('出现 ZeroDivisionError 异常')
# Exception 是所以异常类的父类 所以如果except后跟的是Exception 它会捕获到所有的异常
except Exception as e:
print('出现异常了',e,type(e))
finally:
print('无论是否出现异常 都会执行')
print('异常出现后')
运行结果
异常出现前
出现异常了 list index out of range <class 'IndexError'>
无论是否出现异常 都会执行
异常出现后
1.4 自定义异常对象
1 抛出异常
可以是用raise语句来抛出异常,raise语句后面需要跟一个异常类或者是异常的实例
抛出异常的目的,告诉调用者这里调用时可能出现问题,希望你自己处理下,定义异常类 只需要继承Exception就可以了
下面举例具体说明一下
定义一个Error的类,继承Exception
class Error(Exception):
pass
def seek(a,lst):
if a > len(lst):
# raise Exception('索引大于列表长度')
raise Error('输入的索引太大啦')#自定义异常信息'
return lst[a]
l = [1,2,3]
seek(4,l)
运行结果
__main__.Error: 输入的索引太大啦