1.异常处理
python异常处理伪代码如下:
****异常处理****
try:
代码块(欲执行可能出错的代码)
except 异常类型 as 异常名:
代码块(出现上面类型的异常后,会执行的异常处理代码)
except 异常类型 as 异常名:
代码块(出现上面类型的异常后,会执行的异常处理代码)
......(可以嵌入多个except异常处理语句)
else:
代码块(try语句没出错时会执行的代码)
finally:
代码块(最终总会执行的代码)
其中上述伪代码指明了各种确定异常后的处理方式,如果不想指明异常类型,可以直接写成:
except:
如下:
try:
print(10%0)
except:
print('哈哈,出现问题了')
else:
print('没有错误,继续执行')
finally:
print('xx so handsome!')
2.异常传播
---当在函数中出现异常时,如果在函数中处理了异常,则异常不会再传播
---如果函数中未处理异常,则异常会继续向该异常函数的调用处传播
---如果异常函数调用处处理了异常,则异常不会再传播
---如果调用处未处理异常,异常会一直传递到全局作用域(主模块),如果依旧未处理异常,则程序终止,并抛出异常
---当程序出现异常时,所有的异常信息会专门存储到一个异常对象里
---所以,所谓异常传播,就是将异常对象抛给了调用处
以下定义三个函数,其中fn1是异常函数,fn2会调用fn1,fn3会调用fn2:
def fn1():
print('xx is so handsome!') #用来测试函数被执行
print('10/0') #产生异常的代码块
def fn2():
print('xx is best!') #用来测试函数被执行
fn1() #此处调用fn1异常函数
def fn3():
fn2() #此处调用fn2(异常已传播到fn2)
try:
fn3() #执行主程序块
excpt:
print('xx find erro!') #获取到异常时执行的代码
else:
print('no erro happend!') #没有异常时会执行的代码
以上代码,因为fn1产生异常且未作出处理,所以异常会传递到调用fn1的fn2函数上,并且在fn2处也未对异常作出处理,所以异常会一直传递到主程序fn3上。
在fn3处,如果执行执行fn3(),不使用try...except语句对异常处理,最终会抛出如下的异常:
但实际上,我们已经在最后作出了异常处理,所以最后会按照我们定义的处理方式对异常处理如下:
3.异常捕获
异常捕获其实就是通过前面的except语句去实现,其有以下几个特点:
---如果except后面不跟任何内容,则会捕获到所有的异常类型
---如果except后面跟着一个异常类型,则只能捕获到该类型的异常
---except可以重复多次来捕捉不同类型的异常
---exception是所有异常的父类,同样可以捕捉到所有的异常类型
---在异常类型后面跟上 as xx,此时的xx就是异常名,同样也是定义的异常对象
---如果执行的主程序上存在多个错误,程序执行时只会抛出第一个产生的异常类型,等修改完第一个异常后,才会继续依次抛出其它异常
举例如下:
try:
print(c) #c是一个变量,变量未定义,产生第一个异常
print(10/0) #0不能作除数,产生第二个异常
except NameError as e:
print('变量名称错误!', e, type(e)) #捕获第一个异常,并指出异常和异常类型
except ZeroDivisionError as f:
print('被除数不能为0', f, type(f)) #捕获第二个异常,并指出异常和异常类型
except Exception as g:
print('未知错误', g, type(g)) #捕获其它所有异常,并指出各个异常和异常类型
else:
print('程序无措,继续执行!') #无异常时执行的代码
finally:
print('xx is best!') #最终总会执行的代码
如上,主程序存在两个异常,在直接执行时,会捕获到第一个异常并抛出,并不会捕获到第二个异常,其结果如下:
其中分别返回了:
异常处理标识:名称变量错误
具体异常:name 'c' is not defind
异常类型:<class 'NameError'>(y一个名叫NameError的类)
当我们把第一个异常代码去掉或者修改成print('c')后,继续执行程序,才会抛出捕获到第二个异常:
4.自定义异常类
---所有异常的父类都是exception,所以只需要创建一个类继承exception即可,如下:
def MyError(Exception):
pass
5.抛出异常
---使用raise语句来抛出异常
---raise语句后需要跟一个异常类或者异常对象
如下我们定义一个函数:
def add(a,b):
if a < 0 or b < 0: #如果a和b中有一个负数,就向调用处抛出异常
raise MyErro('两个参数中不能有负数') #raise后面跟异常类型或异常实例,此处用我们刚刚自定义的异常类MyError
r = a + b
return r
add(-1, 3) #传入参数并执行add函数
其执行结果如下,因为参数中存在负数,会抛出我们刚刚定义的异常: