Python-异常处理

阅读目录:

  1、异常 Exception

  2、产生异常

  3、异常的捕获

  4、异常类及继承层次

     5、BaseException及子类

  6、Exception 及子类

  7、异常的捕获

  8、as子句

  9、finally 子句

  10、异常嵌套

  11、else语句

  12、异常的捕获时机

  13、总结

 

 

 

 

1、异常 Exception

  错误 和 异常的区别:

    错误:Error

      • 逻辑错误:算法错误,加法写成了减法
      • 笔误:变量名写错了,语法错误
      • 函数或类使用错误,其实这也属于逻辑错误
      • 总之错误是可以避免的

    异常:Exception

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

    错误和异常:

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

    举例:

      异常:

      错误:

    总结:

      一个健壮的程序

      尽可能的避免错误

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

      Python的特点是,将Error放到异常类中。

2、产生异常:

  产生:

    • raise 语句显式的抛出异常(手动抛出)
    • Python解释器自己检测到异常并引发它

  举例:

    解释器自动抛出:

    手动抛出:

    程序会在异常抛出的地方中断执行,如果不捕获,就会提前结束程序(其实是终止当前线程的执行)

    raise:

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

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

       raise IndexError() :无参构造 ----BaseException的派生类
          raise IndexError :无参构造 ----BaseException的派生类
          raise IndexError('index error') :有参构造 ----BaseException的派生类

 

3、异常的捕获

  语法:

1 try2     待捕获异常的代码块,只要出现一条异常,就会终止,后面的执行,跳到except
3 except [异常类型]:
4     异常的处理代码块

 

  举例:

    1:

    2:

    3:

 

4、异常类及继承层次:

  获取BaseException的子类:

 1 def foo(cls, count=0):
 2    for i in cls.__subclasses__():
 3        if count == 0:
 4            print(count * '\t' +   '+-- ' + str(i))
 5        else:
 6             print((count - 1) * '\t'+ '|' + '\t' +  '+-- ' + str(i))
 7        if  i.__subclasses__() :
 8            count += 1
 9            foo(i, count)
10        else:
11            continue
12 
13 
14 foo(BaseException)
View Code

  结果:

 1 +-- <class 'Exception'>
 2 |    +-- <class 'TypeError'>
 3 |    +-- <class 'StopAsyncIteration'>
 4 |    +-- <class 'StopIteration'>
 5 |    +-- <class 'ImportError'>
 6     |    +-- <class 'ModuleNotFoundError'>
 7     |    +-- <class 'zipimport.ZipImportError'>
 8     |    +-- <class 'OSError'>
 9         |    +-- <class 'ConnectionError'>
10             |    +-- <class 'BrokenPipeError'>
11             |    +-- <class 'ConnectionAbortedError'>
12             |    +-- <class 'ConnectionRefusedError'>
13             |    +-- <class 'ConnectionResetError'>
14             |    +-- <class 'BlockingIOError'>
15             |    +-- <class 'ChildProcessError'>
16             |    +-- <class 'FileExistsError'>
17             |    +-- <class 'FileNotFoundError'>
18             |    +-- <class 'IsADirectoryError'>
19             |    +-- <class 'NotADirectoryError'>
20             |    +-- <class 'InterruptedError'>
21             |    +-- <class 'PermissionError'>
22             |    +-- <class 'ProcessLookupError'>
23             |    +-- <class 'TimeoutError'>
24             |    +-- <class 'io.UnsupportedOperation'>
25         |    +-- <class 'EOFError'>
26         |    +-- <class 'RuntimeError'>
27             |    +-- <class 'RecursionError'>
28             |    +-- <class 'NotImplementedError'>
29             |    +-- <class '_frozen_importlib._DeadlockError'>
30             |    +-- <class 'NameError'>
31                 |    +-- <class 'UnboundLocalError'>
32                 |    +-- <class 'AttributeError'>
33                 |    +-- <class 'SyntaxError'>
34                     |    +-- <class 'IndentationError'>
35                         |    +-- <class 'TabError'>
36                     |    +-- <class 'LookupError'>
37                         |    +-- <class 'IndexError'>
38                         |    +-- <class 'KeyError'>
39                         |    +-- <class 'encodings.CodecRegistryError'>
40                         |    +-- <class 'ValueError'>
41                             |    +-- <class 'UnicodeError'>
42                                 |    +-- <class 'UnicodeEncodeError'>
43                                 |    +-- <class 'UnicodeDecodeError'>
44                                 |    +-- <class 'UnicodeTranslateError'>
45                                 |    +-- <class 'io.UnsupportedOperation'>
46                             |    +-- <class 'AssertionError'>
47                             |    +-- <class 'ArithmeticError'>
48                                 |    +-- <class 'FloatingPointError'>
49                                 |    +-- <class 'OverflowError'>
50                                 |    +-- <class 'ZeroDivisionError'>
51                                 |    +-- <class 'SystemError'>
52                                     |    +-- <class 'encodings.CodecRegistryError'>
53                                     |    +-- <class 'ReferenceError'>
54                                     |    +-- <class 'MemoryError'>
55                                     |    +-- <class 'BufferError'>
56                                     |    +-- <class 'Warning'>
57                                         |    +-- <class 'UserWarning'>
58                                         |    +-- <class 'DeprecationWarning'>
59                                         |    +-- <class 'PendingDeprecationWarning'>
60                                         |    +-- <class 'SyntaxWarning'>
61                                         |    +-- <class 'RuntimeWarning'>
62                                         |    +-- <class 'FutureWarning'>
63                                         |    +-- <class 'ImportWarning'>
64                                         |    +-- <class 'UnicodeWarning'>
65                                         |    +-- <class 'BytesWarning'>
66                                         |    +-- <class 'ResourceWarning'>
67                                         |    +-- <class 'locale.Error'>
68                                         |    +-- <class 'warnings._OptionError'>
69 +-- <class 'GeneratorExit'>
70 +-- <class 'SystemExit'>
71 +-- <class 'KeyboardInterrupt'>
View Code

 

 5、BaseException及子类

  BaseException是所有内建异常类的基类

   SystemExit

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

  

  

  如果except语句捕获了该异常,则继续向后进行,如果没有捕获,解释器直接退出当前执行的程序

  Keyboardinterrupt:

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

  测试:

    本地新建一个.py 文件,输入如下代码:  

1 try:
2     import time
3     while True:
4         time.sleep(2)
5         print('_________')
6 except KeyboardInterrupt:
7     print('ctrl + c')
8 print('out')

 

    在cmd中执行该文件,可以通过ctrl + c 结束中断。

 

6、Exception 及子类:

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

  SyntaxError 语法错误:是无法捕获的,直接识别出来。但在python中是归并到异常类的Exception下的子类

  ArithmeticError所有算术引发的异常,其子类有除零异常等。

  LookupError:使用映射的键或序列的索引无效时引发的异常的基类:IndexError,KerError

  自定义异常:

    从Exception继承的类

7、异常的捕获:

  except可以捕获多个异常:

  总结:

    • 捕获规则
      • 捕获是从上到下依次比较,如果匹配,则执行匹配的except语句块
      • 如果被一个except语句捕获,其他except语句就不会再次捕获了
      • 如果没有任何一个except语句捕获到这个异常,则该异常就向外抛出
    • 捕获原则:
      • 从小到大,从具体到宽泛

8、as子句:

  被抛出的异常,应该是异常的实例 ,如何获得这个对象呢,使用as语句。

  

  

      上面是因为,调用无参构造器,事实上 是有参,但没有缺省值所以在调用的时候,产生异常。

 

  关于 raise 的问题:

  

    一般文件open的都是关于OsError的异常,一般 as e 这个e实例,送到日志中去。

 

9、finally 子句:

  finally:最终,即最后一定要执行的,try-----finally语句快中,不管是否发生了异常,都要执行finally的部分。

  

  测试:return必须写在try语句结构中,如果在最上面,直接返回,函数调用结束了。

  

    一般不这样做,return不会写到 except,finally中,很少这样操作。

    如果没有except,就是任何异常都不管,向外抛。

 

  测试嵌套,以及怎么处理文件句柄清理:

  

  

 

  raise用法:

    测试1:

  

    测试2:

  

 

  压制异常:使用return

    测试1:

    测试2:

  

 

10、异常嵌套

  

11、else语句:

  

 

12、异常的捕获时机

  1、立即捕获:

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

    也就是说,可能产生异常,如果出现异常,立即处理。

1 def parse_int(s):
2     try:
3         return int(s)
4     except:
5         return 0
6 print(parse_int('s'))

 

  2、边界捕获:

    封装产生了边界:

    例如:写了一个模块,用户调用这个模块的时候,捕获异常,模块内部不需要捕获,处理异常,一番内部处理了,外部调用者就无法感知了。

    例如:open函数,出现的异常交给调用者处理,文件存在了,就用在创建了,看是否修改还是删除。

    例如:自己写一个雷,使用open函数,但是出现了异常不知道如何处理,就继续往外层抛,一般来说,最外层也是边界,必须处理这个异常了,否则线程退出。

    也就是一句话:提供功能的,就不要捕获异常了,往外抛,让调用者感知到异常。让调用者处理。

13、总结:

  try:

    <>  运行别的代码

  except <异常类>:

    <>  捕获某种类型的异常

  else:

    <>  如果没有发生异常

  finally:

    <> 退出try 时总会执行

  try工作原理:

    1. 如果try 中语句执行时发生异常,搜索except子句,并执行第一个匹配该异常的except子句
    2. 如果try中语句执行时发生异常,却没有匹配的except子句,异常将被递交到外层的try,如果外层不处理这个异常,异常将继续往外【抛,如果都不能处理,则会传递到最外层,如果还是没有处理,就终止异常所在的线程。
    3. 如果try执行时没有发生异常,将执行else语句
    4. 无论try中是否发生异常,finally子句最终 都会执行。

 

posted @ 2018-09-24 22:53  JerryZao  阅读(757)  评论(0编辑  收藏  举报