python之异常处理

一 异常和错误

1 错误:

逻辑错误: 算法写错了,函数或者类使用出错
语法错误:变量名写错了,语法错误

成都做网站、网站制作中从网站色彩、结构布局、栏目设置、关键词群组等细微处着手,突出企业的产品/服务/品牌,帮助企业锁定精准用户,提高在线咨询和转化,使成都网站营销成为有效果、有回报的无锡营销推广。成都创新互联公司专业成都网站建设10年了,客户满意度97.8%,欢迎成都创新互联客户联系。

2 异常(exception)

本意就是意外情况
有一个前提,没有出现上面的错误,也就是说程序写的没有问题,但在某些情况下,会出现一些意外,导致程序无法正常执行下去,异常时不可能避免的,如open函数操作一个文件,文件不存在,或者创建一个文件时已经存在了,或者访问一个网络文件,突然断网了,这就是异常,时意外情况。

3 异常和错误

在高级编程语言中,一般都会有错误和异常的概念,异常是可以捕获的,并被处理,但错误不能被捕获

1 异常

如下

此处是异常,其是Traceback
python之异常处理
解决方式如下:

#!/usr/local/bin/python3.6
#coding:utf-8
try:
    open('test200')  # 以只读的形式打开一个文件,其默认会抛出异常
except  OSError  as  e:
    print (e)

结果如下
python之异常处理

2 错误

python之异常处理

上述出现的是语法错误导致的问题

#!/usr/local/bin/python3.6
#coding:utf-8
try:
    def  0aa():
        pass
except:
    pass

结果如下
python之异常处理

此处的错误是无法被捕获的

二 异常及相关类型:

1 异常捕获基本

#!/usr/local/bin/python3.6
#coding:utf-8
try:
    f=open('test100')  #此处是只读方式打开的文件,不存在,会抛出异常,若此处异常,则下面的语句将不会被执行
    print ('after')
except:# 如果没有异常,则此处将不会被执行,此处相当于异常已经被处理掉了
    print ('NOT  FOUND File')

结果如下
python之异常处理

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')

结果如下
python之异常处理

#!/usr/local/bin/python3.6
#coding:utf-8
def  div(x,y):
    return   x/y  # 此处也叫除零异常
try:
    div(1,0)  # 此种异常成为运行时异常
except:
    print ('Error')

结果如下
python之异常处理

程序会在异常抛出的地方中断。如果不捕获,就会提前结束程序

2 raise 程序异常

raise 后面什么都没有,表示抛出最近一个被激活的异常,如果没有被激活的异常,则抛类型异常,少用

#!/usr/local/bin/python3.6
#coding:utf-8
try:
    1/0  #产生异常
except:
    try:
        raise   # 此处可捕获的最近被激活的异常
    except  Exception  as e:
        print (e)

结果如下:
python之异常处理

无参实例化

#!/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进行调用处理

python之异常处理

此处是进行有参实例化后的结果

#!/usr/local/bin/python3.6
#coding:utf-8
try:
    1/0  #产生异常
except:
    try:
        raise  Exception('My  BDA') # 此处可捕获的最近被激活的异常,此处可对异常进行相关的处理后进行抛出
    except  Exception  as e:
        print (e)

结果如下:
python之异常处理

3 异常匹配捕获

1 异常类及相关层次

python之异常处理

2 各种异常含义

python之异常处理
python之异常处理
python之异常处理

BaseException 是所有异常的祖先类,及就是所有异常的基类

3 SystemExit 异常

#!/usr/local/bin/python3.6
#coding:utf-8
import  sys
try:
    sys.exit()  # 此处调用的是系统退出的指令
except SystemExit:  # 此处匹配SystemExit 系统退出命令
    print ('exit')

结果如下
python之异常处理

匹配其他非SystemExit父类的异常类

#!/usr/local/bin/python3.6
#coding:utf-8
import  sys
try:
    sys.exit()  # 此处调用的是系统退出的指令
except FileNotFoundError:  # 此处匹配SystemExit 系统退出命令,若匹配其他则不会被捕获
    print ('exit')
print ('outer')  # 此处因为退出,因此此处不会被执行

python之异常处理

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')

结果如下
python之异常处理

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())    # 打印其祖先类列表

结果如下
python之异常处理

6 未实现和未实现异常

NotImplemented 和 NotImplementedError
NotImplemented: 是一个值,相当于是一个None
NotImplementedError: 这是一个类,是一个异常,是抛出异常的时候使用的。

如下:
python之异常处理

#!/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()

python之异常处理

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 ('其他异常')

结果如下

python之异常处理

#!/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 ('其他异常')

结果如下

python之异常处理

#!/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 ('其他异常')

python之异常处理

捕获规则

捕获是从上到下依次比较,如果匹配,则执行匹配的except语句,
如果被一个except语句捕获,则其他的except语句不会再次被执行了
如果没有任何一个except语句捕获到这个异常,则该异常向外抛出

异常不能被捕获的情况

#!/usr/local/bin/python3.6
#coding:utf-8
try:
    1/0  #此处异常后下面的语句将不会被执行
except  FileNotFoundError:
    print ('文件不存在')

python之异常处理

8 AS 字句

被抛出的异常,应该是异常的实例,可通过as字句进行获取

#!/usr/local/bin/python3.6
#coding:utf-8
try:
    1/0  #此处异常后下面的语句将不会被执行
except  ArithmeticError  as  e:  # 进行异常的捕获并获取
    print (e,type(e))

python之异常处理


#!/usr/local/bin/python3.6
#coding:utf-8
class  MyException(Exception):  # 自定义异常类
    pass
try:
    raise   MyException  # 抛出类实例,此处是一个空的实例
except  MyException  as  e:
    print (e,type(e)) # 获取类,此处无法获取实例的内容,因为上述没有定义,此处只能获取到其类型

结果如下

python之异常处理

添加信息如下

#!/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)) # 获取类,此处无法获取实例的内容,因为上述没有定义,此处只能获取到其类型

结果如下

python之异常处理

可定义时间等信息加入其中

#!/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()) # 获取类,此处无法获取实例的内容,因为上述没有定义,此处只能获取到其类型

python之异常处理

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')

结果如下
python之异常处理

发现在连接中出现的问题,可以在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的错误 

python之异常处理

修改方式如下 ,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)

python之异常处理

#!/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()

python之异常处理

#!/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()

结果如下
python之异常处理

#!/usr/local/bin/python3.6
#coding:utf-8
def  a1():
    try:
        return  1  #此处的退出不会影响下面finally的执行
    except:
        pass
    finally:
        print ('fin')
print  (a1())

结果如下
python之异常处理

#!/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()))  # 此处抓取返回值

结果如下
python之异常处理

#!/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()))  # 此处抓取返回值

结果如下
python之异常处理

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() # 此处调用函数,返回异常,异常是逐渐向外扩张的

结果如下
python之异常处理

#!/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)

结果如下

python之异常处理

继续抛出异常

#!/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)

结果如下

python之异常处理

#!/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)

结果如下

python之异常处理

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')

结果如下

python之异常处理

抛出异常后会一直向上,直到线程处,若线程不管,则只会挂掉当前线程,不会影响主线程

主线程操作

#!/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()

结果如下
python之异常处理

结论

当前线程如果是主线程,则会导致进程直接退出


总结

内部捕获不到异常,会向外层传递异常
但是如果内层有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()

结果

python之异常处理

#!/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')

结果如下
python之异常处理

没有任何异常发生时,执行

三 总结:

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