python之异常处理
一 异常和错误
1 错误:
逻辑错误: 算法写错了,函数或者类使用出错
语法错误:变量名写错了,语法错误在成都做网站、网站制作中从网站色彩、结构布局、栏目设置、关键词群组等细微处着手,突出企业的产品/服务/品牌,帮助企业锁定精准用户,提高在线咨询和转化,使成都网站营销成为有效果、有回报的无锡营销推广。成都创新互联公司专业成都网站建设10年了,客户满意度97.8%,欢迎成都创新互联客户联系。
2 异常(exception)
本意就是意外情况
有一个前提,没有出现上面的错误,也就是说程序写的没有问题,但在某些情况下,会出现一些意外,导致程序无法正常执行下去,异常时不可能避免的,如open函数操作一个文件,文件不存在,或者创建一个文件时已经存在了,或者访问一个网络文件,突然断网了,这就是异常,时意外情况。
3 异常和错误
在高级编程语言中,一般都会有错误和异常的概念,异常是可以捕获的,并被处理,但错误不能被捕获
1 异常
如下
此处是异常,其是Traceback
解决方式如下:
#!/usr/local/bin/python3.6
#coding:utf-8
try:
open('test200') # 以只读的形式打开一个文件,其默认会抛出异常
except OSError as e:
print (e)
结果如下
2 错误
上述出现的是语法错误导致的问题
#!/usr/local/bin/python3.6
#coding:utf-8
try:
def 0aa():
pass
except:
pass
结果如下
此处的错误是无法被捕获的
二 异常及相关类型:
1 异常捕获基本
#!/usr/local/bin/python3.6
#coding:utf-8
try:
f=open('test100') #此处是只读方式打开的文件,不存在,会抛出异常,若此处异常,则下面的语句将不会被执行
print ('after')
except:# 如果没有异常,则此处将不会被执行,此处相当于异常已经被处理掉了
print ('NOT FOUND File')
结果如下
2 产生异常
1 产生方式
1 raise 语句显式抛出异常
2 python解释器自己检测到异常并引发他
1 python自发异常
#!/usr/local/bin/python3.6
#coding:utf-8
def div(x,y):
return x/y # 此处也叫除零异常
try:
div(1,0) # 此种异常成为运行时异常
except: # 此处不写,默认匹配所有异常
print ('Error')
结果如下
#!/usr/local/bin/python3.6
#coding:utf-8
def div(x,y):
return x/y # 此处也叫除零异常
try:
div(1,0) # 此种异常成为运行时异常
except:
print ('Error')
结果如下
程序会在异常抛出的地方中断。如果不捕获,就会提前结束程序
2 raise 程序异常
raise 后面什么都没有,表示抛出最近一个被激活的异常,如果没有被激活的异常,则抛类型异常,少用
#!/usr/local/bin/python3.6
#coding:utf-8
try:
1/0 #产生异常
except:
try:
raise # 此处可捕获的最近被激活的异常
except Exception as e:
print (e)
结果如下:
无参实例化
#!/usr/local/bin/python3.6
#coding:utf-8
try:
1/0 #产生异常
except:
try:
raise Exception #此处是无参实例化异常抛出,此处会将上述异常覆盖,此下将不会有情况,此处抛出的是一个实例
except Exception as e:
print (e.__class__.mro()) # 此处__class__表示是获取其实例对应的类,并通过mro进行调用处理
此处是进行有参实例化后的结果
#!/usr/local/bin/python3.6
#coding:utf-8
try:
1/0 #产生异常
except:
try:
raise Exception('My BDA') # 此处可捕获的最近被激活的异常,此处可对异常进行相关的处理后进行抛出
except Exception as e:
print (e)
结果如下:
3 异常匹配捕获
1 异常类及相关层次
2 各种异常含义
BaseException 是所有异常的祖先类,及就是所有异常的基类
3 SystemExit 异常
#!/usr/local/bin/python3.6
#coding:utf-8
import sys
try:
sys.exit() # 此处调用的是系统退出的指令
except SystemExit: # 此处匹配SystemExit 系统退出命令
print ('exit')
结果如下
匹配其他非SystemExit父类的异常类
#!/usr/local/bin/python3.6
#coding:utf-8
import sys
try:
sys.exit() # 此处调用的是系统退出的指令
except FileNotFoundError: # 此处匹配SystemExit 系统退出命令,若匹配其他则不会被捕获
print ('exit')
print ('outer') # 此处因为退出,因此此处不会被执行
4 KeyboardInterrupt 异常,外界键盘输出的异常 ,对应的是Ctrl+C,需要在系统上执行,在pycharm中Ctrl+c 是复制
如下
#!/usr/local/bin/python3.6
#coding:utf-8
import sys
try:
import time
while True:
time.sleep(3) # 此处是一个死循环,可通过外界CTRL+C 进行终止,则打印如下信息
pass
except KeyboardInterrupt:
print ('ctl + c')
print ('outer')
结果如下
5 Exception 及其子类
Exception 是所有内建的,非系统退出的异常的基类,自定义类应该集成自它。
SyntaxError 语法错误,python将其归类到异常下的Exception中,但其不能被捕获。
ArithmeticError 所有算术计算引发的异常,其子类有除零异常情况等
LookupError 使用映射的键或序列的索引无效时引发的异常基类:IndexError,KeyError 等
自定义异常
#!/usr/local/bin/python3.6
#coding:utf-8
class MyException(Exception): # 自定义类,继承至内部的基类
pass
try:
raise MyException() # 实例化调用并抛出异常
except MyException:
print (MyException.mro()) # 打印其祖先类列表
结果如下
6 未实现和未实现异常
NotImplemented 和 NotImplementedError
NotImplemented: 是一个值,相当于是一个None
NotImplementedError: 这是一个类,是一个异常,是抛出异常的时候使用的。
如下:
#!/usr/bin/poython3.6
#conding:utf-8
# this is test
print (type(NotImplemented))
print (type(NotImplementedError))
class A:
def show(self):
raise NotImplementedError
A().show()
7 同时捕获多个异常
#!/usr/local/bin/python3.6
#coding:utf-8
class MyException(Exception): # 自定义类,继承至内部的基类
pass
try:
1/0 #此处异常后下面的语句将不会被执行
open('test100')
raise MyException() # 实例化调用并抛出异常
except MyException: #其匹配方式是从上向下进行匹配,若匹配到,则直接返回结果,下面的将不会被再次匹配
print (MyException.mro()) # 打印其祖先类列表
except ArithmeticError:
print ('除零错误')
except FileNotFoundError:
print ('文件不存在')
except:
print ('其他异常')
结果如下
#!/usr/local/bin/python3.6
#coding:utf-8
class MyException(Exception): # 自定义类,继承至内部的基类
pass
try:
# 1/0 #此处异常后下面的语句将不会被执行
open('test100') #此处匹配文件异常
raise MyException() # 实例化调用并抛出异常
except MyException: #其匹配方式是从上向下进行匹配,若匹配到,则直接返回结果,下面的将不会被再次匹配
print (MyException.mro()) # 打印其祖先类列表
except ArithmeticError:
print ('除零错误')
except FileNotFoundError:
print ('文件不存在')
except:
print ('其他异常')
结果如下
#!/usr/local/bin/python3.6
#coding:utf-8
class MyException(Exception): # 自定义类,继承至内部的基类
pass
try:
# 1/0 #此处异常后下面的语句将不会被执行
# open('test100') #此处匹配文件异常
raise MyException() # 实例化调用并抛出异常
except MyException: #其匹配方式是从上向下进行匹配,若匹配到,则直接返回结果,下面的将不会被再次匹配
print ('自定义异常') # 打印其祖先类列表
except ArithmeticError:
print ('除零错误')
except FileNotFoundError:
print ('文件不存在')
except:
print ('其他异常')
捕获规则
捕获是从上到下依次比较,如果匹配,则执行匹配的except语句,
如果被一个except语句捕获,则其他的except语句不会再次被执行了
如果没有任何一个except语句捕获到这个异常,则该异常向外抛出
异常不能被捕获的情况
#!/usr/local/bin/python3.6
#coding:utf-8
try:
1/0 #此处异常后下面的语句将不会被执行
except FileNotFoundError:
print ('文件不存在')
8 AS 字句
被抛出的异常,应该是异常的实例,可通过as字句进行获取
#!/usr/local/bin/python3.6
#coding:utf-8
try:
1/0 #此处异常后下面的语句将不会被执行
except ArithmeticError as e: # 进行异常的捕获并获取
print (e,type(e))
#!/usr/local/bin/python3.6
#coding:utf-8
class MyException(Exception): # 自定义异常类
pass
try:
raise MyException # 抛出类实例,此处是一个空的实例
except MyException as e:
print (e,type(e)) # 获取类,此处无法获取实例的内容,因为上述没有定义,此处只能获取到其类型
结果如下
添加信息如下
#!/usr/local/bin/python3.6
#coding:utf-8
class MyException(Exception): # 自定义异常类
pass
try:
raise MyException('My Exception') # 抛出类实例,此处是一个空的实例
except MyException as e:
print (e,type(e)) # 获取类,此处无法获取实例的内容,因为上述没有定义,此处只能获取到其类型
结果如下
可定义时间等信息加入其中
#!/usr/local/bin/python3.6
#coding:utf-8
import datetime
class MyException(Exception): # 自定义异常类
pass
try:
raise MyException('My Exception') # 抛出类实例,此处是一个空的实例
except MyException as e:
print (e,type(e),datetime.datetime.now()) # 获取类,此处无法获取实例的内容,因为上述没有定义,此处只能获取到其类型
4 finally
是必须被执行的语句
#!/usr/local/bin/python3.6
#coding:utf-8
import datetime
class MyException(Exception):
def __init__(self,xdata=10):
self.xdata=xdata
try:
raise MyException # 本身自己出错,被底层服务捕获,构造时出现的异常,因此类型异常时从此出现的
except ArithmeticError as e:
print (e,type(e),e.__class__,datetime.datetime.now().timestamp())
except OSError :
print ('操作系统异常')
finally: #此处是否抛出异常,此代码都会被执行
print ('fin')
结果如下
发现在连接中出现的问题,可以在finally中进行处理,其处理的是最终的清理工作,资源的释放工作,和上下文是一样的
#!/usr/local/bin/python3.6
#coding:utf-8
try:
f = open('test.txt')
except FileNotFoundError as e:
print ('{} {} {}'.format(e.__class__,e.errno,e.strerror))
finally:
print ('清理工作')
f.close() # 上述的文件不存在,因此其f不存在,因此会报NameError的错误
修改方式如下 ,finally中添加异常处理
#!/usr/local/bin/python3.6
#coding:utf-8
try:
f = open('test.txt')
except FileNotFoundError as e:
print ('{} {} {}'.format(e.__class__,e.errno,e.strerror))
finally:
print ('清理工作')
try:
f.close() # 上述的文件不存在,因此其f不存在,因此会报NameError的错误
except NameError as e:
print (e)
#!/usr/local/bin/python3.6
#coding:utf-8
f=None
try:
f = open('test.txt')
except FileNotFoundError as e:
print ('{} {} {}'.format(e.__class__,e.errno,e.strerror))
finally:
print ('清理工作')
if f is not None:
f.close()
#!/usr/local/bin/python3.6
#coding:utf-8
try:
f = None # 此处定义f,此处定义和全局定义相同,但一般不建议这样操作
f = open('test.txt')
except FileNotFoundError as e:
print ('{} {} {}'.format(e.__class__,e.errno,e.strerror))
finally:
print ('清理工作')
if f is not None:
f.close()
结果如下
#!/usr/local/bin/python3.6
#coding:utf-8
def a1():
try:
return 1 #此处的退出不会影响下面finally的执行
except:
pass
finally:
print ('fin')
print (a1())
结果如下
#!/usr/local/bin/python3.6
#coding:utf-8
def a1():
try:
1/0 #此处异常后,下面的return将不会被执行,默认返回为None
return "1" #此处的退出不会影响下面finally的执行
except: # 此处表示所有异常都捕获
pass
finally:
print ('fin')
print ("result={}".format(a1())) # 此处抓取返回值
结果如下
#!/usr/local/bin/python3.6
#coding:utf-8
def a1():
try:
1/0 #此处异常后,下面的return将不会被执行,默认返回为None
return "1" #此处的退出不会影响下面finally的执行
except: # 此处表示所有异常都捕获
print ('Error')
finally:
return 100 # 此处定义return,将会覆盖上面的return,且此return下面的语句将不会被执行
print ("result={}".format(a1())) # 此处抓取返回值
结果如下
5 异常传递
#!/usr/local/bin/python3.6
#coding:utf-8
def a1():
try:
1/0 # 此处的异常未被处理
finally:
print ('a1')
def a2():
try:
a1() # 此处调用同上面,返回异常
finally:
print ('a2')
a2() # 此处调用函数,返回异常,异常是逐渐向外扩张的
结果如下
#!/usr/local/bin/python3.6
#coding:utf-8
def a1():
try:
1/0 # 此处的异常未被处理
finally:
print ('a1')
def a2():
try:
a1() # 此处调用同上面,返回异常
except ArithmeticError as e: #在此处处理a1的异常
print ('a2',e)
finally:
print ('a2')
try:
a2() # 此处调用函数,返回异常,异常是逐渐向外扩张的
except ArithmeticError as e: #因为a2处已经处理了异常,此处不需要再次处理相关异常
print ('out',e)
结果如下
继续抛出异常
#!/usr/local/bin/python3.6
#coding:utf-8
def a1():
try:
1/0 # 此处的异常未被处理
finally:
print ('a1')
def a2():
try:
a1() # 此处调用同上面,返回异常
except ArithmeticError as e: #在此处处理a1的异常
print ('a2',e)
raise e #此处持续抛出异常,使得后面继续执行
finally:
print ('a2')
try:
a2() # 此处调用函数,返回异常,异常是逐渐向外扩张的
except ArithmeticError as e: #因为a2处已经处理了异常,此处不需要再次处理相关异常
print ('out',e)
结果如下
#!/usr/local/bin/python3.6
#coding:utf-8
def a1():
try:
1/0 # 此处的异常未被处理
finally:
print ('a1')
def a2():
try:
a1() # 此处调用同上面,返回异常
finally:
print ('a2')
open('aaaaaaaa') # 此处出现异常,则外边会忽略上面的异常,而执行此异常
try:
a2() # 此处调用函数,返回异常,异常是逐渐向外扩张的
except ArithmeticError as e: #因为a2处已经处理了异常,此处不需要再次处理相关异常
print ('out',e)
except FileNotFoundError as e:
print ('file',e)
结果如下
finally 无法处理异常,其执行进行相关的清理工作
Finally 中出现异常若不管,则外层需要有异常处理和捕获机制
线程级别的问题
#!/usr/local/bin/python3.6
#coding:utf-8
import threading
import time
def foo1():
try:
1/0
finally:
print ('foo1 fin')
def foo2():
time.sleep(4)
try:
foo1() #
finally:
print ('foo2 fin')
open('acdvsacdsad')
while True: # 上面的foo1() 不跑出异常,则此处的while True会一直执行,此处执行,则线程会一直执行,此处下面的会一直检测,检测状态
#为存活状态
time.sleep(1)
t=threading.Thread(target=foo2) # 创建线程对象,此处的foo2 会产生异常,t的线程是否会影响死线程
t.start()
while True: # 当前线程是死循环
time.sleep(1)
print ('-------------------------')
if t.is_alive():
print ('alive')
else:
print ('dead')
结果如下
抛出异常后会一直向上,直到线程处,若线程不管,则只会挂掉当前线程,不会影响主线程
主线程操作
#!/usr/local/bin/python3.6
#coding:utf-8
import threading
import time
def foo1():
try:
1/0
finally:
print ('foo1 fin')
def foo2():
time.sleep(4)
try:
foo1() #
finally:
print ('foo2 fin')
open('acdvsacdsad')
while True: # 上面的foo1() 不跑出异常,则此处的while True会一直执行,此处执行,则线程会一直执行,此处下面的会一直检测,检测状态
#为存活状态
time.sleep(1)
while True: # 当前线程是死循环
time.sleep(1)
print ('-------------------------')
foo2()
结果如下
结论
当前线程如果是主线程,则会导致进程直接退出
总结
内部捕获不到异常,会向外层传递异常
但是如果内层有finally且其中有return,break语句,则异常就不会继续向外抛出
异常捕获时机
1 立即捕获,不要将异常向外处理,需要立即返回一个明确的结果
#!/usr/local/bin/python3.6
#coding:utf-8
def a1():
try:
f=open('100')
except FileNotFoundError as e:
print (e)
return 1 # 若匹配此处则返回此值
except FileExistsError as e:
print (e)
return 2
finally:
print ('aaaa')
a1()
结果
#!/usr/local/bin/python3.6
#coding:utf-8
def getaint(data): # 数字的转换
try:
res=int(data)
except Exception: #此处若有异常,则直接返回为0,此处是立即捕获,立即处理
res=0
return res
2 边界捕获
封装产生了边界
如: 写了一个模块,用户调用这个模块的时候捕获异常,模块内部不需要捕获,处理异常,一旦内部处理了,外部调用者就无法感知了
例如 open 函数,出现的异常交给调用者处理,文件存在了,就不需要创建了,看是否修改还是删除
一般的,自己写了一个类,使用了open函数,但是出现了异常不知道如何处理,就继续向外抛出,一般说最外层也是边界,必须处理这个异常,否则线程将会退出
一般的,给外部提供某些功能的函数是不建议在内部进行处理操作的
业务的分界,模块的外部
6 else
try:
1/0
except Exception:
print ('except')
except:
pass
else: # 此处针对没有异常时执行的动作
print ('else')
finally:
print ('fin')
结果如下
没有任何异常发生时,执行
三 总结:
1 语句结构
try:
<语句> #运行的代码
except <异常类>:
<语句> # 捕获某种异常的类型
except <异常类> as <变量名>:
<语句> # 捕获某种类型的异常并获取对象
else:
<语句> #如果没有发生异常
2 概念总结
1 如果try 中语句执行时发生异常,搜索except字句,并执行第一个匹配该异常的except字句
2 如果try中语句执行时发生异常,却没有匹配的except字句,异常将被递交到外层try,如果外层不处理这个异常,异常将继续向外层传递,如果都补处理该异常,则会传递到最外层,如果没有处理,就终止异常所在的线程
3 如果try执行时没有异常,则执行else字句中的语句
4 无论try中是否发生异常,finally字句最终都会被执行
网页名称:python之异常处理
文章位置:http://myzitong.com/article/gjgoid.html