Python专题异常和工具.docx
《Python专题异常和工具.docx》由会员分享,可在线阅读,更多相关《Python专题异常和工具.docx(19页珍藏版)》请在冰点文库上搜索。
![Python专题异常和工具.docx](https://file1.bingdoc.com/fileroot1/2023-5/8/4f392e59-02af-4eff-8bd7-02e79804c68c/4f392e59-02af-4eff-8bd7-02e79804c68c1.gif)
Python专题异常和工具
1.异常基础
try/except:
捕捉由python或程序员引起的异常并恢复。
try/finally:
无论异常是否发生,执行清理语句
raise:
手动在代码中触发异常
assert:
有条件的在代码中触发异常
with/as:
在python2.6和后续版本中实现环境管理器
1.1为什么使用异常?
异常处理对于错误处理、终止动作和事件通知有用。
它可以简化特殊情况的处理,并且可以用来实现替代的控制流程。
一般来讲,异常处理还可以减少程序所需的检测错误代码的数量,因为所有的错误都由处理器来过滤,你可能不需要测试每个操作的输出。
1.2异常的角色
错误处理
事件通知
特殊情况处理
终止行为
非常规控制流程
2.异常处理
2.1默认异常处理器
如果代码没有刻意的捕捉代码异常,它将会一直向上返回程序顶层,并启用默认的异常处理器:
就是打印标准出错消息。
这些消息引发的异常还有堆栈跟踪:
也就是异常发生时激活的程序行和函数清单。
deffetcher(obj,index):
returnobj[index]
x='spam'
fetcher(x,4)
output:
Traceback(mostrecentcalllast):
File"C:
\E\workspace\PythonLearning\chapter17\exc.py",line6,in
fetcher(x,4)
File"C:
\E\workspace\PythonLearning\chapter17\exc.py",line2,infetcher
returnobj[index]
IndexError:
stringindexoutofrange
任何未捕获的异常都流入默认的异常处理器,python在程序的最顶端提供它。
这个处理器打印类似的出错消息,并且退出程序。
2.2捕获异常:
try/except/else语句
try:
fetcher(x,4)
exceptIndexError:
print'gotexception'
try首行底下的代码块代表此语句的主要动作:
试着执行程序代码。
Except子句定义了try代码块内引发的异常的处理器,而else子句则是提供没发生异常时要执行的处理器。
●如果try代码块语句执行时的确发生了异常,python就跳回try,执行第一个符合引发异常的except子句下面的语句。
当except代码块执行后(除非except代码块又引发了另一异常),控制权就会到整个try语句后继续执行。
●如果异常发生在try代码块内,没有符合的except子句,异常就会向上传递到程序中的之前进入的try中,或者如果它是第一条这样的语句,就传递到这个进程的顶层(这回使Python终止这个程序并打印默认的出错消息)。
●如果try首行底下执行的语句没有发生异常,python就会执行else下的语句(如果有的话),控制权会在整个try语句下继续。
2.2.1Try语句分句
Python3.0引入了一个替代方案,捕获一个名为Exception的异常几乎与一个空的except具有相同的效果。
2.2.2Try/else分句
如果没有else,是无法知道控制流程(没有设置和检查布尔标志)是否已经通过try语句,因为没有异常引发或者因为异常发生了且已被处理过了。
2.3终止行为:
try/finally语句
Try/finally组合,可以定义一定会在最后执行时的收尾行为,无论try代码块中是否发生了异常,finally代码块都会执行。
defafter():
try:
fetcher(x,4)
finally:
print'afterfetch'
print'aftertry?
'
Output:
afterfetch
Traceback(mostrecentcalllast):
File"C:
\E\workspace\PythonLearning\chapter17\exc.py",line13,in
after()
File"C:
\E\workspace\PythonLearning\chapter17\exc.py",line8,inafter
fetcher(x,4)
File"C:
\E\workspace\PythonLearning\chapter17\exc.py",line3,infetcher
returnobj[index]
IndexError:
stringindexoutofrange
Try/except的组合可用于捕捉异常从中恢复,而try/finally的组合则很方便,可以确保无论try代码块内的代码是否发生了任何异常,终止行为一定会运行。
●如果try代码块运行时没有异常发生,python会跳至执行finally代码块,然后在整个try语句后继续执行下去。
●如果try代码块运行时有异常发生,python依然会回来运行finally代码块,但是接着会把异常向上传递到较高的try语句或顶层默认处理器。
程序不会再try语句下继续执行。
Finally子句的用途:
指明一定要执行的“清理”动作,无论异常发生了没有。
classMyError(Exception):
pass
defstuff(file):
raiseMyError()
file=open('data','w')
try:
stuff(file)
finally:
file.close()
print'notreached'
2.4统一try/except/finally语句
●如果该程序代码引发异常,那么所有except代码块都会逐一测试,寻找与抛出异常相符的语句。
如果没有引发异常则会执行else-block。
●无论之前发生什么,当main-action代码块完成时,而任何引发的异常都已处理后,finally-block就会执行。
即使异常处理器或者else-block内有错误发生而引起了新的异常,finally-block内的程序代码依然会执行。
●当finally-block执行时,如果异常还存在,就会在finally-block代码块执行后继续传递,而控制权会跳到程序其他地方(到另一个try,或者默认的顶层处理器)。
如果finally执行时,没有异常处于激活状态,控制权就会在整个try语句之后继续下去。
sep='-'*32+'\n'
printsep+'EXCEPTIONRAISEDANDCAUGHT'
try:
x='spam'[99]
exceptIndexError:
print'exceptrun'
finally:
print'finallyrun'
print'afterrun'
printsep+'NOEXCEPTIONRAISED'
try:
x='spam'[3]
exceptIndexError:
print'exceptrun'
finally:
print'finallyrun'
print'afterrun'
printsep+'NOEXCEPTIONRAISED,WITHELSE'
try:
x='spam'[3]
exceptIndexError:
print'exceptrun'
else:
print'elserun'
finally:
print'finallyrun'
print'afterrun'
printsep+'EXCEPTIONRAISEDBUTNOTCAUGHT'
try:
x=1/0
exceptIndexError:
print'exceptrun'
finally:
print'finallyrun'
print'afterrun'
Output:
--------------------------------
EXCEPTIONRAISEDANDCAUGHT
exceptrun
finallyrun
afterrun
--------------------------------
NOEXCEPTIONRAISED
finallyrun
afterrun
--------------------------------
NOEXCEPTIONRAISED,WITHELSE
elserun
finallyrun
afterrun
--------------------------------
EXCEPTIONRAISEDBUTNOTCAUGHT
finallyrun
Traceback(mostrecentcalllast):
File"C:
\E\workspace\PythonLearning\chapter17\mergedexc.py",line33,in
x=1/0
ZeroDivisionError:
integerdivisionormodulobyzero
2.5Raise语句
raise
raise
raise
Raise语句的组成是:
raise关键字,后面跟着可选的要引发的类或者类的实例,raise语句不包括异常名称和额外数据值时,就是重新引发当前异常。
2.6Assert语句
Assert,
Assert可视为条件式的raise语句,如果test为假,python就会引发AssertionError异常:
data项是异常的额外数据。
Assert几乎都是用来收集用户定义的约束条件,而不是捕捉内在程序设计错误。
2.7With/as环境管理器
With语句的基本格式:
Withexpression[asvariable]:
With-block
With/as语句的设计,是为了让必须在程序代码块周围发生的启动和终止活动一定会发生。
和try/finally语句(无论异常是否发生,其离开动作都会执行)类似,但是with/as有更丰富的对象协议,可以定义进入和离开的动作。
2.7.1环境管理协议
With语句实际的工作方式:
1.计算表达式,所得到的对象称为环境管理器,它必须有__enter__和__exit__方法。
2.环境管理器的__enter__方法会被调用。
如果as子句存在,其返回值会赋值给As子句中的变量,否则丢弃。
3.代码块中嵌套的代码会执行。
4.如果with代码块引发异常,__exit__(type,value,traceback)方法就会被调用。
5.如果with代码块没有引发异常,__exit__方法依然会被调用,其type、value以及traceback参数会以None传递。
classTraceBlock:
defmessage(self,arg):
print'running',arg
def__enter__(self):
print'startingwithblock'
returnself
def__exit__(self,exc_type,exc_value,exc_tb):
ifexc_typeisNone:
print'exitednormally\n'
else:
print'raiseanexception!
',exc_type
returnFalse
withTraceBlock()asaction:
action.message('test1')
print'reached'
withTraceBlock()asaction:
action.message('test2')
raiseTypeError
print'notreached'
Output:
Traceback(mostrecentcalllast):
File"C:
\E\workspace\PythonLearning\chapter17\withas.py",line20,in
raiseTypeError
TypeError
startingwithblock
runningtest1
reached
exitednormally
startingwithblock
runningtest2
raiseanexception!
3.异常对象
内置异常和用户定义的异常都可以通过类实例对象来表示。
基于类的异常有如下特点:
●提供类型分类,对今后的修改有更好的支持。
●它们附加了状态信息
●它们支持继承
3.1基于类的异常
Python2.6和python3.0都要求异常通过类来定义。
此外python3.0要求异常类派生自BaseException内置异常超类,而不管直接还是间接。
字符串异常在python2.6和python3.0之中已经删除,因为它们都是通过简单的对象标识来匹配,所以它们没有直接的方式来把异常组织到更为灵活的领域。
classGeneral(Exception):
pass
classSpecific1(General):
pass
classSpecific2(General):
pass
defraise0():
X=General()
raiseX
defraise1():
X=Specific1()
raiseX
defraise2():
X=Specific2()
raiseX
forfuncin(raise0,raise1,raise2):
try:
func()
exceptGeneral:
importsys
print'caught:
',sys.exc_info()
Output:
caught:
(,General(),)
caught:
(,Specific1(),)
caught:
(,Specific2(),)
3.2为什么使用类异常?
Mathlib.py
classNumErr(Exception):
pass
classDivzero(NumErr):
pass
classOflow(NumErr):
pass
...
deffunc():
...
raiseDivzero()
Client.py
importmathlib
...
try:
mathlib.func(...)
exceptmathlib.NumErr:
...reportandrecover...
3.3内置Exception类
BaseException:
异常的顶级根类。
这个类不能当作是由用户定义的类直接继承。
Exception:
与应用相关的异常的顶层根超类。
ArithmeticError:
所有数值错误的超类。
OverflowError:
识别特定的数值错误的子类。
Exception是python中所有应用程序级别的异常的超类,通常可以使用它作为一个全捕获。
3.3.1默认打印和状态
内置异常还提供了默认打印显示和状态保持,传递给异常类的任何构造函数参数都会保存在实例的args元组属性中,并且打印该实例的时候自动显示。
>>>raiseIndexError
Traceback(mostrecentcalllast):
File"",line1,in
raiseIndexError
IndexError
>>>raiseIndexError('spam')
Traceback(mostrecentcalllast):
File"",line1,in
raiseIndexError('spam')
IndexError:
spam
>>>I=IndexError('spam')
>>>I.args
('spam',)
>>>
classE(Exception):
pass
try:
raiseE('spam','eggs','ham')
exceptEasX:
printX,X.args
Output:
('spam','eggs','ham')('spam','eggs','ham')
3.4定制打印显示
classMyBad(Exception):
def__str__(self):
return"Alwayslookonthebrightsideoflife..."
try:
raiseMyBad()
exceptMyBadasX:
printX
raiseMyBad()
Output:
Traceback(mostrecentcalllast):
File"C:
\E\workspace\PythonLearning\chapter17\mathlib.py",line10,in
raiseMyBad()
__main__.MyBad:
Alwayslookonthebrightsideoflife...
Alwayslookonthebrightsideoflife...
3.5定制数据和行为
3.5.1提供异常细节
classFormatError(Exception):
def__init__(self,line,file):
self.line=line
self.file=file
defparser():
raiseFormatError(42,file='spam.txt')
try:
parser()
exceptFormatErrorasX:
print"Errorat",X.file,X.line
printX.args
Output:
Erroratspam.txt42
()#默认构造函数被重写
3.5.2提供异常方法
classFormatError(Exception):
logfile='formaterror.txt'
def__init__(self,line,file):
self.line=line
self.file=file
deflogerror(self):
log=open(self.logfile,'a')
print>>log,'Errorat{0}{1}'.format(self.file,self.line)
defparser():
raiseFormatError(42,file='spam.txt')
try:
parser()
exceptFormatErrorasX:
print"Errorat",X.file,X.line
printX.args
X.logerror()
Output:
Erroratspam.txt42
()
4.异常的设计
4.1嵌套异常处理器
4.2异常的习惯用法
4.2.1异常不总是错误
●内置的input函数在每次调用时,则是从标准输入串流sys.stdin读取一行文字,并且在文件末尾时引发内置的EOFError。
●Input的空字符串是指空行。
除了EOFError的名称,这个异常在这种环境下也只是信号而已,不是错误。
●调用sys.exit()并在键盘上按下ctrl-C,会分别引发SystemExit和KeyboardInterput。
4.2.2函数信号条件和raise
classFound(Exception):
pass
defsearcher():
ifTrue:
raiseFound()
else:
return
try:
searcher()
exceptFound:
print"success"
else:
print"failure"
这种代码结构,可用于任何无法返回经是值以表明成功或失败函数。
异常提供一种方式来传达结果信号,而不是使用返回值。
4.2.3关闭文件和服务器连接
异常处理工具通常用来确保系统资源终结,不管在处理过程中是否发生了错误。
确保一个代码块的终止操作的更通用和显式的方式式try/finally语句:
myfile=open(r'C:
\misc\script','w')
try:
...processmyfile...
finally:
myfile.close()
With/as语句运行的环境管理器:
withopen(r'C:
\misc\script','w')asmyfile:
...processmyfile...
4.2.4在try外进行调试
try:
...runprogram...
except:
importsys
print"uncaught!
",sys.exc_info()[0],sys.exc_info()[1]
4.2.5运行进程中的测试
importsys
log=open('testlog','a')
fromtestapiimportimportmoreTests,runNextTest,testName
deftestdriver():
whilemoreTests():
try:
runNextTest()
except:
print'FAILED',testName(),sys.exc_info()[:
2]
else:
print'PASSED',testName()
testdriver()
4.2.6关于sys.exc_info()
Sys.exc_info()允许一个异常处理器获取对最近引发的异常的访问。
如果没有处理器正在处理,就返回了三个None值的元组。
否则,将会返回(type、value和traceback)。
●Type是正在处理的异常的异常类型
●Value是引发的异常的异常类实例
●Traceback是一个traceback对象,代表异常最初发生时所调用的堆栈。
l=[1,2]
try:
l[3]
except:
importsys
prin