错误与异常
目录:
----------什么是错误与异常
1、1、异常类
----------捕捉异常并处理
1、try...except的初步使用
2、try...except的捕获异常分析(一)
3、try...except的捕获异常分析(二)
4、try...except的捕获异常分析(三)
5、try...except的捕获异常分析(四)
6、try ... except...else的捕获异常分析(一)
7、try ... finally....的捕获异常分析(一)
8、try ... except....finally....的捕获异常分析(综合应用)
9、With语句的捕获异常分析(综合应用)
----------raise和assert语句
1、raise语句
2、assert语句
----------标准异常和自定义异常
一、什么是错误与异常?
错误:在执行前就出现错误
1、语法错误:代码不符合解释器或者编译器语法
2、逻辑错误:不完整或者不合法输入或者计算出现问题
异常:执行过程中出现问题导致程序无法执行
1、程序遇到逻辑或者算法问题
2、运行过程中计算错误(内存不够或者IO错误)
错误与异常的区别:
错误:
1、代码运行前的语法或者逻辑错误
2、语法错误在执行前修改,逻辑错误无法修改
异常:代码运行后的
1、异常产生,检查错误且解释器认为是异常,跑出异常
2、异常处理,截获异常,忽略或者终止程序处理异常
Python中用异常对象来表示异常情况。通常遇到错误后,就会引发异常,每一个异常都是一些类的实例。这些实例可以被引发,并且可以用很多种方法 进行捕捉,是的程序可以捕捉错误并对其进行处理。
1.Python异常类
Python是面向对象语言,所以程序抛出的异常也是类。常见的Python异常有以下几个,大家只要大致扫一眼,有个映像,等到编程的时候,相信大家肯定会不只一次跟他们照面(除非你不用Python了)。
Python中的内建异常类
异常 |
描述 |
NameError |
尝试访问一个没有申明的变量 |
ZeroDivisionError |
除数为0的错误 |
SyntaxError |
语法错误 |
IndexError |
索引超出序列范围 |
KeyError |
请求一个不存在的字典关键字 |
IOError |
输入输出错误(比如你要读的文件不存在) |
AttributeError |
尝试访问未知的对象属性 |
ValueError |
传给函数的参数类型不正确,比如给int()函数传入字符串形 |
例子:常见的错误---代码运行前
>>> a
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
a
NameError: name ‘a‘ is not defined
例子:常见的异常---代码运行后
>>> print (1/0)
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
print (1/0)
ZeroDivisionError: division by zero
>>> while True print("Hello World")
SyntaxError: invalid syntax
二、捕捉异常并处理
===============================================================================
try...except的初步使用
python中的异常使用继承结构创建,可以在异常处理程序中捕获基类异常,也可以捕获各种子类异常,python中使用try...except语句捕获异常,异常子句定义在try子句后面。
try子句中的代码块放置可能出现异常的语句,except子句中的代码块处理异常。
语法的整体结构
解释:
1、try是用来捕获try_suite块中的错误,并且将错误交给except处理。
2、try下面的try_suite块指的是需要被处理的逻辑代码,检测是否具有异常。
3、except是用接收try所捕获的异常的,如果处理异常和设置捕获异常一致,使用Exception_block处理异常。(当处理异常和设置捕获异常不一致时,此异常就会被解释器直接处理。)
4、后面的Exception是指内建异常类,称为设置异常,用来与try_suite块所捕获到的异常类相匹配,看看是否相等。
5、.[e] 是指变量,用于保存所出现的错误异常的信息。(如果处理异常和捕获异常不一致时,它就是用来保存解释器直接处理的错误信息。)
6、exception_block指的的用来处理捕获异常的逻辑。
例子:
[[email protected] ~]# cat error.py
#!/usr/bin/python
a
print "exec over"
[[email protected] ~]# ./error.py
Traceback (most recent call last):
File "./error.py", line 2, in <module>
a
NameError: name ‘a‘ is not defined
解析:
这里的a和print "exec over"是属于同一个程序块,a没有被定义,所以不能输出。
例子:
[[email protected] ~]# cat error.py
#!/usr/bin/python
try:
a
except NameError,e:
print "catch Error:",e
print "exec over"
[[email protected] ~]# ./error.py
catch Error: name ‘a‘ is not defined
exec over
解析:
try捕获到a没有被定义就使用了,将存在的异常交给except处理,捕获异常与处理异常类型一致,e指的是存放处理信息,捕捉到的异常被处理得到的信息就是“name ‘a‘ is not defined”。print "exec over"和上面的异常程序没有关系,直接就是所见即所得。
例子:
[[email protected] ~]# cat error.py
#!/usr/bin/python
a = 0
try:
a
except NameError,e:
print "catch Error:",e
print "exec over"
[[email protected] ~]# ./error.py
exec over
解析:
这里的a被定义了,不存在异常,异常程序也就不会有输出,直接就执行异常程序外的语句
===============================================================================
try...except的捕获异常分析(一)
例子:可以捕获异常,因为是运行时出现错误
[[email protected] ~]# cat test.py
#!/usr/bin/python
try:
undef
except:
print "catch an except"
[[email protected] ~]# ./test.py
catch an except
解析:
undef是在运行过程中没有被定义的,存在异常,异常程序段中匹配到异常,从而得以输出。
例子:不能捕获异常,因为是语法错误,运行前出现错误
[[email protected] ~]# cat test.py
#!/usr/bin/python
try:
if undef
except:
print "catch an except"
[[email protected] ~]# ./test.py
File "./test.py", line 3
if undef
^
SyntaxError: invalid syntax
解析:
先说说python的代码执行过程:在执行异常段程序之前,Python先把代码(.py文件)用解释器编译成二进制的字节码,在此编译过程中会先检查语法结构是否正确,如果语法结构是正确的,就交给字节码虚拟机(如果语法结构是错误的,在编译的过程中就会把这个错误给抛出来),然后虚拟机一条一条执行字节码指令,从而完成程序的执行。
if undef是语法错误,也就是此异常程序运行之前的。所以异常程序块根本就不会执行,也就不会捕捉到异常。
===============================================================================
try...except的捕获异常分析(二)
例子:异常单处理
代码:
[[email protected] ~]# cat firstpy.py
#!/usr/bin/python
try:
x = input(‘Enter the first number:‘)
y = input(‘Enter the second number:‘)
print x/y
except ZeroDivisionError: #匹配捕获异常和设置异常类型是否一致
print "Exception: can‘t you enter the denominator is zero" #异常处理快语句
代码执行结果
[[email protected] ~]# ./firstpy.py
Enter the first number:10
Enter the second number:0
Exception: can‘t you enter the denominator is zero
解析:
try检测到代码的异常,交给了except进行处理,except将捕获异常和设置异常进行匹配,发现捕获异常的类型和设置异常的类型是一致的,就会执行异常处理块语句。
问题来了:
当设置异常的类型是与try:检测出的异常不相同时会出现上面结果呢?
代码:
[[email protected] ~]# cat firstpy.py
#!/usr/bin/python
try:
x = input(‘Enter the first number:‘)
y = input(‘Enter the second number:‘)
print x/y
except NameError: #匹配捕获异常和设置异常类型是否一致
print "Exception: can‘t you enter the denominator is zero"
结果:
[[email protected] ~]# ./firstpy.py
Enter the first number:10
Enter the second number:0
Traceback (most recent call last):
File "C:\Users\yu\Desktop\yichang.py", line 3, in <module>
print x/y
ZeroDivisionError: integer division or modulo by zero
解析:
except开始处理异常时,发现设置异常(NameError)的类型和捕捉异常(ZeroDivisionError)的类型不一致,except就会自动的忽略掉捕捉到的异常,然后将捕捉到的异常向上抛,抛给了python解释器,python解释器会处理这个异常,python解释器处理的默认形式就是终止代码的运行。
===============================================================================
try...except的捕获异常分析(三)
例子:多个异常处理--捕获多个异常
当捕捉异常与设置异常的类型不相同时,那这个时候,这个异常就会逃过异常的处理并导致程序的终止。那么为了避免出现这个现象,从而捕捉到这个异常,怎么做呢?可以在try/except语句后面加上多个except子句。
代码:
[[email protected] ~]# cat firstpy.py
#!/usr/bin/python
try:
x = input(‘Enter the first number:‘)
y = input(‘Enter the second number:‘)
print x/y
except TypeError:
print "Function of the type error"
except ZeroDivisionError:
print "Exception: can‘t you enter the denominator is zero"
except SyntaxError:
print "Grammar mistakes"
执行代码结果:
[[email protected] ~]# ./firstpy.py
Enter the first number:10
Enter the second number:‘2‘
Function of the type error
Enter the first number:10
Enter the second number:0
Exception: can‘t you enter the denominator is zero
解析:
当捕捉异常与设置异常的类型不相同时,python会终止程序,然后捕捉异常会匹配下一个设置异常的类型是否一致,如果一致,就会输出except的处理块,并且不会继续匹配。如果依旧是不一致的,依然会终止程序,再次进行匹配。
问题又来了
1、使用多个except子句是不是很烦
2、怎么能够一次性多匹配内建异常类型呢?
例子:匹配多个设置异常---捕获多个异常
代码
[[email protected] ~]# cat firstpy.py
#!/usr/bin/python
try:
x = input(‘Enter the first number:‘)
y = input(‘Enter the second number:‘)
print x/y
except (ZeroDivisionError,TypeError):
print "Detect abnormalities"
代码的执行结果
[[email protected] ~]# ./firstpy.py
Enter the first number:10
Enter the second number:‘1‘
Detect abnormalities
[[email protected] ~]# ./firstpy.py
Enter the first number:10
Enter the second number:0
Detect abnormalities
[[email protected] ~]# ./firstpy.py
Enter the first number:10
Enter the second number:/0
Traceback (most recent call last):
File "./firstpy.py", line 4, in <module>
y = input(‘Enter the second number:‘)
File "<string>", line 1
/0
^
SyntaxError: invalid syntax
分析:
想要一次性匹配多个异常类,直接在except后面加上括号,里面写入要匹配的异常类,用逗号隔开。检测异常匹配异常类有两个ZeroDivisionError,TypeError。上述的执行结果有三个,前面连个都被匹配到了,报出了“Detect abnormalities”信息。第三个是没有检测到的,python解释器终止运行。
===============================================================================
try...except的捕获异常分析(四)
例子:捕捉对象本身
代码
[[email protected] ~]# cat firstpy.py
#!/usr/bin/python
try:
x = input(‘Enter the first number:‘)
y = input(‘Enter the second number:‘)
print x/y
except (ZeroDivisionError,TypeError),e:
print e
结果
[[email protected] ~]# ./firstpy.py
Enter the first number:10
Enter the second number:0
integer division or modulo by zero
[[email protected] ~]# ./firstpy.py
Enter the first number:10
Enter the second number:‘1‘
unsupported operand type(s) for /: ‘int‘ and ‘str‘
例子:真正的全力捕捉
为了避免一些异常没有被检测到,我们不能把所有的异常类型都写下进行匹配,想要实现这个要求,方法很简单,就是在except子句后面什么都不加。
代码:
[[email protected] ~]# cat firstpy.py
#!/usr/bin/python
try:
x = input(‘Enter the first number:‘)
y = input(‘Enter the second number:‘)
print x/y
except (ZeroDivisionError,TypeError),e:
print e
===============================================================================
try ... except...else的捕获异常分析(一)
Python中有很多特殊的else用法,比如用于条件和循环。放到try语句中,其作用其实也差不多:就是当没有检测到异常的时候,则执行else语句。
例子:try ... except...else的简单认识
代码:
while True:
try:
x = input(‘Enter the first number:‘)
y = input(‘Enter the second number:‘)
value = x/y
print ‘x/y is‘, value
except: #匹配到异常执行下面的语句
print ‘please try again‘
else: #没有匹配到异常就跳出循环
break
结果
=================RESTART:C:\Users\yu\Desktop\yichang.py=================
>>>
Enter the first number:10
Enter the second number:0
please try again
Enter the first number:10
Enter the second number:‘1‘
please try again
Enter the first number:10
Enter the second number:2
x/y is 5
分析:
在循环里只有没有异常引发的情况下才会推出循环,只有异常发生,程序会不断的要求你重新输入。
例子:处理信息存储到e中
代码
while True:
try:
x = input(‘Enter the first number:‘)
y = input(‘Enter the second number:‘)
value = x/y
print ‘x/y is‘, value
except Exception,e:
print ‘input:‘,e
print ‘please try again‘
else:
break
结果
==================RESTART:C:\Users\yu\Desktop\yichang.py=================
Enter the first number:10
Enter the second number:0
input: integer division or modulo by zero
please try again
Enter the first number:10
Enter the second number:‘1‘
input: unsupported operand type(s) for /: ‘int‘ and ‘str‘
please try again
Enter the first number:10
Enter the second number:2
x/y is 5
===============================================================================
try ... finally....的捕获异常分析(一)
finally子句是无论是否检测到异常,都会执行的一段代码。我们可以丢掉except子句和else子句,单独使用try...finally,也可以配合except等使用。
try ... finally语句的基本结构
处理过程:
1、如果try语句没有捕捉到异常,就直接执行do_finally语句块。
2、如果try语句捕捉到了异常,程序首先会执行do_finally语句块,然后将捕捉到的异常交给python解释器处理。
例子:存在异常
代码:
x = None
try:
x = 10/0
finally:
print ‘Cleaning up.....‘
del x
解析:
try检测到异常,执行finally子句,然后将捕捉到的异常发给python解释器处理,python解释器会直接终止运行程序。运行这段代码,在程序崩溃之前,对于变量x的清理就完成了
在try子句之前初始换x的原因是如果不这样做的话,由于ZeroDIVISIONerror的存在,x就不会被赋值。这样就会导致finally子句中使用del删除他的时候发生异常,而且这个异常是无法捕捉的。
结果:
=================RESTART:C:\Users\yu\Desktop\yichang.py==================
Cleaning up.....
Traceback (most recent call last):
File "C:\Users\yu\Desktop\yichang.py", line 3, in <module>
x = 10/0
ZeroDivisionError: integer division or modulo by zero
例子:不存在异常
代码
x = None
try:
x = 10/2
finally:
print ‘Cleaning up.....‘
del x
结果
===================RESTART:C:/Users/yu/Desktop/test.py===================
Cleaning up.....
>>>
解析:
Try语句捕捉到异常,直接执行finally子句块。
===============================================================================
try ... except....finally....的捕获异常分析(综合应用)
try ... except....finally的基本结构
try ... except....finally的应用过程
1、若try语句没有捕捉到异常,在执行try代码段后,直接执行finaly。
2、若try捕捉到异常,首先会执行except处理异常,然后执行finally
例子:try语句没有捕捉到异常
代码:
x = None
try:
x = 10/2
except ZeroDivisionError:
print "Exception: can‘t you enter the denominator is zero"
finally:
print ‘Cleaning up.....‘
del x
结果:
=================RESTART:C:/Users/yu/Desktop/except.py=================
Cleaning up.....
分析:
这里没有捕捉到异常,直接执行了finally语句
例子:try语句捕捉到了异常
代码:
x = None
try:
x = 10/0
except ZeroDivisionError:
print "Exception: can‘t you enter the denominator is zero"
finally:
print ‘Cleaning up.....‘
del x
结果:
=================RESTART:C:/Users/yu/Desktop/except.py=================
Exception: can‘t you enter the denominator is zero
Cleaning up.....
分析
这里捕捉到了异常。(捕捉异常与设置异常类型一致)先是执行except语句,然后执行finally语句。
===============================================================================
With语句的捕获异常分析(综合应用)
With语句的基本结构
With语句的使用过程
1、with语句用来代替try...except...finally语句,是代码更加简洁
2、context表达式返回的是一个上下文管理器对象
3、var用来保存context返回对象。var可以是单个变量,或者由“()”括起来的元组(不能是仅仅由“,”分隔的变量列表,必须加“()”)
4、with_suite 使用var变量来对context返回对象进行操作
with语句实质是上下文管理:
1、上下文管理协议:包含方法 __enter__() 和 __exit__(),支持该协议的对象要实现这两个方法。
2、上下文管理器:支持上下文管理协议的对象,这种对象实现了__enter__() 和 __exit__() 方法。上下文管理器定义执行 with 语句时要建立的运行时上下文,负责执行 with 语句块上下文中的进入与退出操作。通常使用 with 语句调用上下文管理器,也可以通过直接调用其方法来使用。
3、运行时上下文:由上下文管理器创建,通过上下文管理器的 __enter__() 和
__exit__() 方法实现,__enter__() 方法在语句体执行之前进入运行时上下文,__exit__() 在语句体执行完后从运行时上下文退出。with 语句支持运行时上下文这一概念。
4、上下文表达式:with 语句中跟在关键字 with 之后的表达式,该表达式要返回一个上下文管理器对象。
5、语句体(with-body):with 语句包裹起来的代码块,在执行语句体之前会调用上下文管理器的 __enter__() 方法,执行完语句体之后会执行 __exit__() 方法。
例子:with语句实例
分析:
1、打开1.txt文件
2、打开文件后,open(‘1.txt’)语句会返回一个对象,将这些对象保存在f中
3、With中的代码执行完成后,就关闭文件。如果代买执行时出现异常,首先管关闭文件,然后在进程处理异常。
代码:使用 with 语句操作文件对象
with open(r‘somefileName‘) as somefile:
for line in somefile:
print line
# ...more code
分析:
这里使用了 with 语句,不管在处理文件过程中是否发生异常,都能保证 with 语句执行完毕后,被打开的文件句柄都已经关闭了。如果使用传统的 try/finally 范式,则要使用类似如下代码:
代码:try/finally 方式操作文件对象
somefile = open(r‘somefileName‘)
try:
for line in somefile:
print line
# ...more code
finally:
somefile.close()
分析:
比较起来,使用 with 语句可以减少编码量。已经加入对上下文管理协议支持的还有模块 threading、decimal 等。
例子:with 语句执行过程
context_manager = context_expression
exit = type(context_manager).__exit__
value = type(context_manager).__enter__(context_manager)
exc = True # True 表示正常执行,即便有异常也忽略;False 表示重新抛出异常,需要对异常进行处理
try:
try:
target = value # 如果使用了 as 子句
with-body # 执行 with-body
except:
# 执行过程中有异常发生
exc = False
# 如果 __exit__ 返回 True,则异常被忽略;如果返回 False,则重新抛出异常
# 由外层代码对异常进行处理
if not exit(context_manager, *sys.exc_info()):
raise
finally:
# 正常退出,或者通过 statement-body 中的 break/continue/return 语句退出
# 或者忽略异常退出
if exc:
exit(context_manager, None, None, None)
# 缺省返回 None,None 在布尔上下文中看做是 False
过程分析:
1、执行 context_expression,生成上下文管理器 context_manager
2、调用上下文管理器的 __enter__() 方法;如果使用了 as 子句,则将 __enter__() 方法的返回值赋值给 as 子句中的 target(s)
3、执行语句体 with-body
4、不管是否执行过程中是否发生了异常,执行上下文管理器的 __exit__() 方法,__exit__() 方法负责执行“清理”工作,如释放资源等。如果执行过程中没有出现异常,或者语句体中执行了语句 break/continue/return,则以 None 作为参数调用 __exit__(None, None, None) ;如果执行过程中出现异常,则使用 sys.exc_info 得到的异常信息为参数调用 __exit__(exc_type, exc_value, exc_traceback)
5、出现异常时,如果 __exit__(type, value, traceback) 返回 False,则会重新抛出异常,让with 之外的语句逻辑来处理异常,这也是通用做法;如果返回 True,则忽略异常,不再对异常进行处理.
总结
with是对try…expect…finally语法的一种简化,并且提供了对于异常非常好的处理方式。在Python有2种方式来实现with语法:class-based和decorator-based,2种方式在原理上是等价的,可以根据具体场景自己选择。
三:raise和assert语句
===============================================================================
---------raise语句
Raise语句用于主动跑出异常,从而结束异常。
例子:
>>> a = 10
>>> b = 0
>>> raise a/b
Traceback (most recent call last):
File "<pyshell#28>", line 1, in <module>
raise a/b
ZeroDivisionError: integer division or modulo by zero
===============================================================================
----------assert语句
1、assert语句用来声明某个条件是真的。
2、如果你非常确信某个你使用的列表中至少有一个元素,而你想要检验这一点,并且在它非真的时候引发一个错误,那么assert语句是应用在这种情形下的理想语句。
3、当assert语句失败的时候,会引发一AssertionError。
例子:
>>> list1 = [‘information‘,‘Genal‘,‘23‘,‘man‘]
>>> len(list1)
4
>>> assert len(list1) > =4 #判定list1中元素大于等于4个的,判定为真,
>>> list1.pop()
‘man‘
>>> len(list1)
3
>>> assert len(list1) > =4
Traceback (most recent call last):#判定list1中元素大于等于4个的,判定为假。
File "<pyshell#23>", line 1, in <module>
assert len(list1) > 3
AssertionError
四:标准异常和自定义异常
===============================================================================
----------标准异常
----------自定义异常
自定义异常:
1、Python允许自定义异常,用于描述python中没有涉及的异常情况
2、自定义异常必须继承Exception类
3、自定义异常只能主动触发
自定义异常示例:
例子:
>>> class FileError(IOError):
pass
>>> raise FileError,"Test FileError"
Traceback (most recent call last):
File "<pyshell#36>", line 1, in <module>
raise FileError,"Test FileError"
FileError: Test FileError
例子:
>>> try:
raise FileError,"Test FileError"
except FileError,e:
print e
Test FileError
例子:
代码:
class CustomError(Exception):
def _init_(self,info):
Exception,_init_(self)
self,errorinfo = info
def _str_(self):
return "CustionError:%s" % self,errorinfo
try:
raise CustomError("test CustomError")
except CustomError,e:
print "ErrorInfo:%s" %(e)
结果
================= RESTART: C:/Users/yu/Desktop/exception2.py =================
ErrorInfo:test CustomError
>>>