Python中异常处理

1、异常 Exception

错误Error

逻辑错误:算法写错了,加法写成了减法。

笔误:变量名写错了,语法错误。

错误可以避免的

 

异常Exception

本身就是意外情况。一些意外,导致程序无法正常的执行下去。

是不可避免的。

 

错误和异常

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

with open('test') as f:
    pass

 

错误信息:

Traceback (most recent call last):

  File "C:/Users/WCL/PycharmProjects/untitled1/package/test1/异常处理.py", line 1, in <module>

    with open('test') as f:

FileNotFoundError: [Errno 2] No such file or directory: 'test'

 

def 0A():
    pass

 

  File "C:/Users/WCL/PycharmProjects/untitled1/package/test1/参数检查.py", line 142

    class typeassert

                   ^

SyntaxError: invalid syntax

 

一个健壮的程序,尽可能的避免错误。

尽可能的捕获,处理各种异常。

 

2、产生异常

产生:raise语句显示的抛出异常。

Python解释器自己检测到异常并引发他。

def foo():
    print('-----')
    def bar():
        print(1/0)
    bar()
    print('after')
foo()

def bar():
    print('+++++++++++++')
    raise Exception('Exc')
    print('+-+-+-+-+-+')
bar()

 

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

 

raise语句

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

raise

后要求应该是BaseException类的子类或实例,如果是类,将被无参实例化。

异常必须出自BaseException

sys.exc_info()查看异常所在的元素。

sys.exc_info() ,后面是个元组。(异常类、异常对象,trackback)

 

 

3、异常捕获

try:

  待捕获异常的代码块  

except[异常类型]:

异常的处理代码块

 

try:
    print('++++++++++++++++')
    c = 1/0
    print('----------------')
except:
    print('catch the exception')
print('outer')

 

++++++++++++++++

catch the exception

Outer

执行到c = 1/0时候产生异常并抛出,由于使用了语句捕捉这个异常,所以产生异常位置后面的语句将不再执行了,转而执行对象except以外的语句。

2)捕获指定类型的异常。

try:
    print('++++++++++++++++')
    c = 1/0
    print('----------------')
except ArithmeticError:
    print('catch the ArithmeticError:')
print('outer')

 

 

++++++++++++++++

catch the ArithmeticError:

Outer

 

 

 

 

 

特别关心的异常放在最上面。

自己定义的异常。

Exception 非退出性异常。

捕获原则:

4、异常类即继承层次

def exc_hierarchy(exc=BaseException, level=-1):
    name = exc.__name__
    if level == -1:
        print(name)
    else:
        print("{} +-- {}".format('    ' * level, name))
    for sub in exc.__subclasses__():
        exc_hierarchy(sub, level+1)

 

BaseException

 +-- Exception

     +-- StopAsyncIteration

     +-- OSError

         +-- BlockingIOError

         +-- FileNotFoundError

         +-- IsADirectoryError

         +-- TimeoutError

         +-- InterruptedError

         +-- ProcessLookupError

         +-- NotADirectoryError

         +-- ConnectionError

             +-- BrokenPipeError

             +-- ConnectionAbortedError

             +-- ConnectionRefusedError

             +-- ConnectionResetError

         +-- UnsupportedOperation

         +-- FileExistsError

         +-- ChildProcessError

         +-- PermissionError

     +-- ArithmeticError

         +-- FloatingPointError

         +-- OverflowError

         +-- ZeroDivisionError

     +-- AttributeError

     +-- SyntaxError

         +-- IndentationError

             +-- TabError

     +-- SystemError

         +-- CodecRegistryError

     +-- ImportError

         +-- ZipImportError

     +-- BufferError

     +-- LookupError

         +-- IndexError

         +-- KeyError

         +-- CodecRegistryError

     +-- NameError

         +-- UnboundLocalError

     +-- TypeError

     +-- error

     +-- StopIteration

     +-- AssertionError

     +-- Warning

         +-- UserWarning

         +-- DeprecationWarning

         +-- UnicodeWarning

         +-- PendingDeprecationWarning

         +-- ImportWarning

         +-- RuntimeWarning

         +-- ResourceWarning

         +-- SyntaxWarning

         +-- BytesWarning

         +-- FutureWarning

     +-- Error

     +-- ValueError

         +-- UnicodeError

             +-- UnicodeEncodeError

             +-- UnicodeDecodeError

             +-- UnicodeTranslateError

         +-- UnsupportedOperation

     +-- ReferenceError

     +-- RuntimeError

         +-- RecursionError

         +-- NotImplementedError

         +-- _DeadlockError

     +-- MemoryError

     +-- EOFError

 +-- GeneratorExit

 +-- KeyboardInterrupt

 +-- SystemExit

 

 

 

 

5、BaseException及子类

1)BaseException所有内建异常类的基类是BaseException。

 

2)SystemExit

sys.exit()函数引发的异常,异常不捕获处理,就直接交给Python解释器,解释器退出。

 

import sys
print('++++')
sys.exit(1)
print('sysexit')
print('-----')

 

++++

 

Process finished with exit code 1

未进行捕获的情况下,

解释器直接退出了。

 

 

import sys
try:
    print('++++')
    sys.exit(1)
except SystemExit:
    print('sysexit')
print('-----')

 

++++

sysexit

-----

捕获的情况下正常执行,且被捕获。

 

3)Keyboardinterrupt

对应捕获用户中断的行为 Ctrl + c

 

6、Exception及子类

Exception是所有内建的,非系统退出的异常的基类,自定义异常应该定义继承自它。

 

1)SyntaxError语法错误,Python中也归到Exception类中,但是语法错误是不可被捕获的。

2)ArithmeticError所有算数计算引发的异常,其子类有除零异常等。

3)LookupError 使用映射的键或者序列的索引无效是引发的异常的基类:indexerror keyerror

4)自定义的异常:从Exception继承的类。

 

7、异常的捕获

Except可以捕获多个异常。

捕获的原则:捕获是从上到下依次比较,如果匹配,则执行匹配的except语句块。

如果被一个except语句块捕获,其他的except就不会再次捕获了。

如果没有任何一个except语句捕获到这个异常,则该异常向外抛出。

捕获的原则,从小到大,从具体到广泛。

8、as子句

被抛出的异常,应该是异常的实例,获得这个对象的话,使用as子句。

class MyException(Exception):
    def __init__(self,code,message):
        self.code = code
        self.message = message
try:
    raise MyException
except MyException as e:
    print(11111111)
    print('{}{}'.format(e.code,e.message))
except Exception as e:
    print('{}'.format(e))

 

__init__() missing 2 required positional arguments: 'code' and 'message'

raise后面有特定的参数,如果没有的话就是无参形式。

 

9、finally 子句

Finally 最终,即最后都会是要一定执行的。try.....finally不管有没有异常都会执行。

Finally中一般都是放置资源的清理,释放工作的语句。

也可以在finally中再次捕获异常。

10、finally执行时机

def foo():
    try:
        return 3
    finally:
        print('finally')
    print('---')
print(foo())

 

尽管函数有return返回语句,但是finally语句还是要执行的,最后才返回return语句。

拿的值是最后一个return。

11、异常传递

def foo1():
    return 1/0

def foo2():
    print('foo2 ----')
    foo1()
    print('foo2++++')
foo2()

foo2调用了foo1,foo1产生的异常传递到了foo2中

异常总是向外层抛出,如果外层没有处理这个异常,就会继续向外抛出,如果内层捕获并处理了异常,外部就不能捕获的到了。

如果到了最外层还是没有被处理,就会中断异常所在的线程的执行。

import threading
import time

def foo1():
    return 1/0

def foo2():
    time.sleep(3)
    print('foo2----')
    foo1()
    print('foo2++++')
t = threading.Thread(target=foo2)
t.start()

while True:
    time.sleep(1)
    print('Everything OK')
    if t.is_alive():
        print('live')
    else:
        print('dead')

 

未进行捕获异常,异常抛出直接中断了线程。

sys.exc_info() ,后面是个元组。(异常类、异常对象,trackback)

 

 

 

 

12、try 的嵌套

try:
    try:
        ret = 1/0
    except KeyError as k:
        print(k)
    else:
        print('ok')
    finally:
        print('finally')
except:
    print('c ok')
finally:
    print('fin')

 

内部捕获不到异常,会向外层传递异常。

但是如果内层有且有finally而且其中有return、break语句,否则就不会继续往外抛出异常。

 

def foo():
    try:
        ret = 1/0
    except KeyError as F:
        print(k)
    finally:
        print('finally a ')
        return   #异常直接被丢弃
try:
    foo()
except:
    print('+++++')
finally:
    print('-------')

 

有return语句,异常直接被丢弃。

 

13、异常的捕获时机

1)立即捕获

需要立即返回一个明确的结果


def parse_int(s):
    try:
        return int(s)
    except:
        return 0
print(parse_int('s'))

 

被return直接返回0

2)边界捕获

封装产生了边界。

(1)一个模块,用户调用了这个模块的时候捕获异常,异常内部不需要捕获,处理异常,一旦内部处理了,外部调用者无法感知异常了

(2)Open函数,出现的异常交给调用者处理,文件存在,就不用创建了,看是否修改修改还是删除。

(3)自己写了一个类,使用open函数,但是文件出现异常不知道如何处理,就继续向外层抛出,一般来说最外层也是边界,必须处理异常,如果不处理的话,线程就会推出。

14、else子句

 else子句,没有异常发生,则执行。

try:
    ret = 1/0
except ArithmeticError as e:
    print(e)
else:
    print('ok')
finally:
    print('fin')
####division by zero
###fin

 

15、总结

 try:

<语句> #运行别的代码

except<异常类>:

<语句>  #捕获某种类型的异常

except<异常类> as <变量名>:

<语句>   #捕获某种类型的异常并获得对象

else:

<语句> #如果没有异常发生

finally:

<语句>  #推出try的时候总会执行

try的工作原理

(1)如果try中语句执行时候会发生异常,搜索except子句,并执行第一个匹配该异常的except子句。

(2)如果try中语句执行时发生异常,却没有匹配except子句,异常将被递交到外层的try,如果外层不处理这个异常,异常将继续向外层传递,如果都不处理该异常,则会传递到最外层,如果还没有处理,就会终止异常所在的线程。

(3)如果try执行时候没有异常,将执行else子句中的语句。

(4)无论try中是否发生异常,finally子句最终都会执行。

posted @ 2018-11-12 23:19  Python爱好者666  阅读(1296)  评论(0编辑  收藏  举报