赞
踩
一、异常处理
1、错误Error
逻辑错误:算法写错了
笔误:变量名写错了,语法错误
函数或类的使用错误,其实这也属于逻辑错误,错误是可以避免的
2、异常Exception
本意就是意外情况,这有个前提,没有出现上面说的错误,也就是说程序写的没有问题,但是在某些情况下会出现一些意外,导致程序无法正常执行下去
3、错误和异常
在高级编程语言中,一般都是有错误和异常的概念,异常时可以捕获,并被处理的,但是错误是不能被捕获的
一个健壮的程序因尽可能的避免错误,尽可能的捕获、处理各种异常
二、产生异常
1、产生
raise语句显式的抛出异常,python解释器自己检测到异常并引发它
deffoo():print('before')defbar():print(1/0) #除零异常
bar()print('after')
foo()defbar():print('before')raise Exception('my exextion')print('after')
bar()
程序会在异常抛出的地方中断执行,如果不捕获异常,就会提前结束程序
三、异常的捕获
try:
待捕获异常的代码块except[异常类型]
异常的处理代码块try:print('begin')
c=1/0print('end')except:print('catch the exception')print('outer')
上例执行到c=1/0时产生异常b并抛出,由于使用了try...except语句块则捕获到了这个异常
异常生成位置之后语句将不再执行,转而执行对应的except部分的语句,最后执行try...except语句块之外的语句
四、异常类及继承层次
1、BaseException及子类
所有内建异常类的基类是BaseException
2、SystemExit
sys.exit()函数引发的异常,异常不捕获处理,就直接交给python解释器,解释器退出
举例1:importsysprint('before')
sys.exit(1)print('SysExit')print('outer') #是否执行
举例2:#捕获这个异常
importsystry:
sys.exit(1)exceptSystemExit:print('SysExit')print('outer')
举例3:#对应的捕获用户中断行为Ctrl + c
try:importtimewhileTrue:
time.sleep(0.5)pass
exceptKeyboardInterrupt:print('crtl + c')print('outer')
3、Exception及子类
Exception是所有内建的,非系统退出的异常的基类,自定义异常应该继承自它
举例1:defa():try:
0a= 5
except:pass执行报错:
File"", line 40a= 5
^SyntaxError: invalid syntax
SyntaxError语法错误,python将这种错误也归到异常类下面的Exception下的子类,但是这种错误是不可捕获的
ArithmeticError所有算术计算引发的异常,其子类除零异常等
LookupError:使用映射的键或者序列的索引无效时引发的异常的基类:IndexError,KeyError
4、自定义的异常,从Exception继承的类
classMyException(Exception):pass
try:raiseMyException()except: #捕获自定义异常
print('cathc the exception')
五、异常的捕获
1、except可以捕获多个异常
举例1:classMyException(Exception):pass
try:
a= 1/0raise MyException() #自定义的异常
open('a1.txt')except MyException: #捕获自定义异常
print('cathc the MyException')exceptZeroDivisionError:print('1/0')exceptException:print('Exception')
捕获规则:捕获是从上到下依次比较,如果匹配,则执行匹配的except语句块
如果被一个except语句捕获,其他except语句就不会再次捕获了
如果没有任何一个except捕获到这异常,则该异常向外抛出
捕获原则:从小到大,从具体到宽泛
2、as 字句
被抛出的异常,应该是异常的实例,如何获取得到这个对象,使用as字句
举例1:classMyException(Exception):def __init__(self, code, message):
self.code=code
self.message=messagetry:raiseMyException()#raise MyException(200,'ok') #raise后跟类名是无参构造实例,因此需要2个参数
except MyException as e: #捕获自定义异常
print('MyException = {}{}'.format(e.code, e.message))exceptException as e:print('Exception = {}'.format(e))
执行输出:Exception= __init__() missing 2 required positional arguments: 'code' and 'message'
#执行输出:MyException = 200,ok
3、finally子句
即最后一定要执行的语句,try...finally语句块中,不管是否发生了异常,都要执行finally的部分
举例1:
f=Nonetry:
f= open('test.txt')exceptFileNotFoundError as e:print(e)print('{},{},{}'.format(e.__class__, e.errno, e.strerror))finally:print('清理工作')iff:
f.close()1、finally执行时机
测试1:deffoo():try:return 3
finally:print('finally')print('===========')print(foo())
执行报错:finally
3进入try,执行return3,虽然函数要返回,但是finally一定还要执行,所以打印了finally后,函数返回
测试2:deffoo():try:return 3
finally:return 5
print('===========')print(foo())
进入try,执行return3,虽然函数要返回,但是finally一定要执行,所以执行return 5,
函数返回,5被压在栈顶,所以返回5,简单说,函数的返回值取决于最后一个执行的return语句
而finally则是try...finally中最后执行的语句块
六、异常的传递
举例1:deffoo1():return 1/0deffoo2():print('foo2 start')
foo1()print('foo2 stop')
foo2()
foo2调用了foo1,foo1产出的异常,传递到了foo2中
异常总是向外层抛出,如果外层没有处理这个异常,就会继续向外抛出
如果内层捕获并处理了异常,外部就不能捕获到了
如果到了最外层还是没有被处理,就会中断异常所在的线程的执行
举例2:#线程中测试异常
importthreadingimporttimedeffoo1():return 1/0deffoo2():
time.sleep(3)print('foo2 start')
foo1()print('foo2 stop')
t= threading.Thread(target=foo2)
t.start()whileTrue:
time.sleep(1)print('Everthing OK')ift.is_alive():print('alive')else:print('dead')2、try的嵌套
举例1:try:try:
ret= 1/0exceptKeyError as e:print(e)else:print('inner OK')finally:print('inner fin')except:print('outer catch')finally:print('outer fin')
内部捕获不到异常,会向外层传递异常,但是如果内层有finally且其中有return,break语句,则异常就不会继续向外抛出,异常被丢弃
举例2:deffoo():try:
ret= 1/0exceptKeyError as e:print(e)finally:print('inner fin')return #异常被丢弃
try:
foo()except:print('outer catch')finally:print('outer fin')
七、异常的捕获时机
1、立即捕获
需要立即返回一个明确的结果defparse_int(s):try:returnint(s)except:return0print(parse_int('s'))
2、边界捕获
封装产出了边界
例如,写了一个模块,用户调用这个模块的时候捕获异常,模块内部不需要捕获,处理异常一旦内部处理了,外部调用者就无法感知了
例如open函数,出现的异常交给调用者处理,文件存在了,就不用再创建了,看是否修改还是删除
例如自己写了一个类,使用了open函数,但是出现了异常不知道如何处理,就继续向外层抛出
一般来说最外层也是边界,必须处理这个异常了,否则线程退出
3、else子句
没有任何异常发生,则执行try:
ret= 1/0exceptArithemticError as e:print(e)else:print('OK')finally:print('fin')
总结:try: #运行别的代码
except : #捕获某种类型的异常
except as : #捕获某种类型的异常并获得对象
else: #如果没有异常发生
finally: #退出try时总会执行
八、try的工作原理
如果try中语句执行时发生异常,搜索except子句,并执行第一个匹配该异常的except子句
如果try中语句执行时发生异常,却没有匹配的except子句,异常将被递交到外层的try如果外层不处理这个异常,异常将继续向外层传递,如果都不处理该异常,则会传递到最外层,如果还没有处理,就终止异常所在线程
如果在try执行时没有发生异常,将执行else子句中的语句
无论try中是否发生异常,finally子句最终都会执行
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。