一、常见的异常类型:
•SyntaxError:Python 不能理解程序
•NameError:局部或全局变量名找不到
•AttributeError:属性引用失败
•IndexError:索引引用越界
•TypeError:操作数的类型不正确
•ValueError:操作数类型正确,但值非法
•ZeroDivisionError:被零除
•FileNotFoundError:文件未找到
•IOError:IO system 报告故障
二、异常处理
1、try…except的使用
•try…except语句用于处理问题语句,捕获可能出现的异常。
•try子句中的代码块放置可能出现异常的语句,except子句中的代码块处理异常。当异常出现时,Python会自动生成1个异常对象,该对象包括异常的具体信息,以及异常的种类和错误位置。
例题1:
•编写函数getRatios(v1, v2)。
•假定参数v1、v2是等长的数字列表,要求返回一个列表,该列表包含v1[i]/v2[i]有意义的值。
def getRatios(v1,v2):
"""
Assumes v1 and v2 are lists of equal length of numbers
ReturnsLa list containing the meaningful values of
v1[i]/v2[i]
"""
ratios=[]
for index in range(len(v1)):
try:
ratios.append(v1[index]/(v2[index]))
except ZeroDivisionError:
ratios.append(float('NaN')) # NaN= Not a Number
except:
raise ValueError('getRatioscalled with bad arg')
return ratios
try:
print(getRatios([1.0,2.0,7.0,6.0],[1.0,2.0,0.,3.0,]))
print(getRatios([],[]))
print(getRatios([1.0,2.0],[3.0]))
except ValueError as msg:
print(msg)
输出结果:
[1.0, 1.0, nan, 2.0]
[]
getRatioscalled with bad arg
例题2:
使用try…except捕获FileNotFoundError异常
try:
open('hello.txt','r') #尝试打开一个不存在的文件
print('读文件')
except FileNotFoundError:
print('文件不存在')
except :
print('程序异常')
输出结果:
文件不存在
例题3:
捕获并处理除数为0的ZeroDivisionError异常
def div(x,y):
try:
result=x/y
except ZeroDivisionError: #捕获除数为0的异常
print('0 不能做除数')
else: #若没有异常则执行以下代码
print(result)
div(10,0)
div(10,5)
输出结果:
0 不能做除数
2.0
例题4:异常处理嵌套
#异常处理嵌套
def strtest(s):
try:
print(s[6])
try: #嵌套异常
print(s[0]+s[1])
print(s[0]-s[1])
except TypeError:
print('字符串不支持减法运算')
except:
print('异常')
strtest('hello')
strtest('Hello world!')
输出结果:
异常
w
He
字符串不支持减法运算
2、try…finally的使用
•try…except语句还可以添加1个finally子句,无论异常是否发生,finally子句都会被执行。
•finally子句通常用于关闭因异常而不能释放的系统资源。
例题5:用try......处理异常
try:
number1,number2=eval(input('Enter two numbers,seperated by a comma:'))
result=number1/number2
except ZeroDivisionError:
print('Division by zero!')
except SyntaxError:
print('A comma may be missing in the input')
except:
print('Something wrong in the input')
else:
print('No exceptions,the result is',result)
finally:
print('executing the final clause')
输出结果:
3、使用raise抛出异常
•当程序中出现错误时,Python会自动引发异常。另外,在程序的任何地方都可以使用raise语句故意引发异常。
•一旦执行了raise语句,raise语句后的代码将不被执行。
•raise语句通常用于抛出自定义异常,因为自定义异常并不在Python的控制范围之内,不会被Python自动抛出,应使用raise语句手工抛出。
例题6:使用raise抛出异常
#使用raise 抛出异常
def object(s):
try:
if s is None:
print('s是空对象')
raise NameError
print(len(s))
except NameError:
print('空对象没有长度')
object(None)
object('abc')
object([1,2,3,4])
object([])
输出结果:
s是空对象
空对象没有长度
3
4
0
4、自定义异常
•Python允许自定义异常,用于描述Python异常体系中没有涉及的异常情况。
•自定义异常必须继承Exception类。
•自定义异常按照命名规范以Error结尾,显式地表示该类是异常类。
•自定义异常使用raise语句引发,且只能通过手工方式触发。
例题7:自定义异常
#自定义异常
class DivisionExceptionError(Exception):
def __init__(self,x,y):
Exception.__init__(self,x,y)
self.x=x
self.y=y
if __name__=='__main__':
x=int(input('input a number:'))
y=int(input('input another number:'))
try:
if x>0 and y>0:
print(x/y)
else:
raise DivisionExceptionError(x,y) #抛出异常
except DivisionExceptionError as div:
print('arguments are error!')
print('x=',div.x,'y',div.y)
输出结果:
5、断言
•在没完善一个程序之前,我们不知道程序在哪里会出错,与其让它在运行时崩溃,不如在出现错误条件时就崩溃。
•使用断言的目的是为了尽早识别bug且清楚它们是在何处出现的
–在第一次碰到问题时就捕获它,使调试更容易,而不是之后再追踪
•若用户提供了错误输入时应尽可能依靠抛出异常去处理,而断言常用于检查参数或值的类型。
•assert语句用于检测某个条件表达式是否为真。
•assert语句又称为断言语句,即assert认为检测的表达式永远为真。
•if语句中的条件判断都可以使用assert语句检测。例如,检测某个元组中元素的个数是否大于1,如果assert语言断言失败,会引发AssertionError异常。
#assert语句使用
t=('hello',)
assert len(t)>=1
t=('hello')
assert len(t)==1
输出结果:
assert len(t)==1
AssertionError
带异常参数的断言语句:
•arguments]
•功能:用来解释断言并更好的知道是哪里出了问题
lst=[1,2,3,4,5,6]
assert len(lst)>=5, '列表元素个数小于5'
lst=[1,2,3,4]
assert len(lst)>=5, '列表元素个数小于5'
输出结果:
File "C:/Users/Administrator/.spyder-py3/temp.py", line 4, in <module>
assert len(lst)>=5, '列表元素个数小于5'
AssertionError: 列表元素个数小于5
6、多种异常的处理
•可在except子句中指定多种异常来处理多种异常;
•如果要分别处理不同的异常,可使用多个except子句;
•如果在except子句中没有指定异常,它将捕获所有异常。
例题9:处理多种异常
#处理多种异常
def convert_to_int1(s,base): #指定多种异常
try:
return int(s,base)
except (ValueError,TypeError):
return 'error'
def convert_to_int2(s,base): #分别处理多种异常
try:
return int (s,base)
except ValueError:
return 'value error'
except TypeError:
return 'type error'
def convert_to_int3(s,base):
try:
return int(s,base)
except:
return 'error'
x1=convert_to_int1(8,10)
print(x1)
x1=convert_to_int1('abc',10)
print(x1)
x2=convert_to_int2(8,10)
print(x2)
x2=convert_to_int2('abc',10)
print(x2)
x3=convert_to_int3(8,10)
print(x3)
x3=convert_to_int3('abc',10)
print(x3)
输出结果:
error
error
type error
value error
error
error
三、调试
•如果总能写出正确的代码,并在第一次测试时就能正确执行,当然很好。但实际编程过程中并不总是如此顺利。
•如何测试代码是否正确,常用的方法有:
–黑盒测试—通过特定规范执行路径
–白盒测试—通过代码执行路径
–将调试作为一个搜索过程—使用二分查找的方法,分离并检查错误来源
1、测试和调试
•在调试程序过程中我们需要一些方法:
–测试方法—使用不同的例子运行代码看其是否正确的方法
–调试方法—已经发现程序中有问题,如何修正程序的方法
- 何时进行测试?何时进行调试?
•实际上,如果能弄清楚如何设计代码,那么测试和调试会更加简单。优秀的程序员会有这样的经验:
–将代码分解成独立的模块,从而独立地测试和调试;
–写出好的文档(写明输入、输出的期望是什么;即使代码没有执行对测试的限制,这种文档也是有价值的);
–记录可能的各种假设;
-
测试之前要完成的工作:
•确保代码可以运行
–剔除语法错误
–剔除静态语义错误
–事实上,Python解释器可以自动处理上述两种错误
•准备一套预期结果(即对于一个特定的输入,期待会有怎样的输出)
2、测试套件
•找到一系列输入,它们很有可能暴露错误,且不会花太多时间,但却十分有效,这就是所谓测试套件。
–将输入分解为子集,为代码正确性提供等效信息;
–构造测试套件,其中至少包含每个子集的一个元素;
–运行测试套件。
测试方法:
•随机测试:代码的正确率随测试次数的增加而增加;
•黑盒测试:在测试时,把程序看作一个不能打开的黑盒子,在完全不考虑程序内部结构和内部特性的情况下,测试者在程序接口进行测试,它只检查程序功能是否按照需求规格说明书的规定正常使用,程序是否能适当地接收和正确的输出
•白盒测试:是通过程序的源代码进行测试而不使用用户界面。这种类型的测试需要从代码句法发现内部代码在算法,溢出,路径,条件等等中的缺点或者错误,进而加以修正。