Loading

python异常处理

异常 Exception

  • 错误 Error

    逻辑设计错误、笔误、语法错误,即在运行前可以避免的

  • 异常Exception

    程序执行时的意外情况,前提是没有上面的错误情况,但在某些情况下出现的意外导致程序无法正常执行。

    例如open函数操作一个文件,但文件不存在,或网络访问一个文件,突然断网了,就是异常。

异常可以捕获,但错误是不能捕获的

产生异常

  • Pyhon解释器检测到异常并引发
def foo():
    print('before')
    def bar():
        print(1/0)   # 除0异常

    bar()
    print('after')

foo()  # 运行时会直接抛出
  • raise语句显示抛出异常
def bar():
    print('before')
    raise Exception('my exception')  # 显示抛出异常
    print('after')  # raise后的语句不在执行

bar()

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

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

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

异常的捕获

# 语法
try:
  待捕获异常的代码块
except [异常类型]:
  异常处理的代码块

示例:

def bar():
    try:
        print('begin')
        c = 1/0
        print('end')
    except:
        print('catch the exception')

bar()

# 执行到1/0异常时,由于使用了try...except捕获到异常,则异常生成位置之后语句将不再执行,转而执行对应的except部分语句
begin
catch the exception

捕获指定类型的异常

try:
    print('begin')
    c = 1/0
    print('end')
except ArithmeticError:   # 数值计算类型异常,可以正常捕获
    print('catch the exception')



try:
    print('begin')
    c = 1/0
    print('end')
except KeyboardInterrupt:  # 用户中断执行(通常是输入^C),1/0异常不属于这种类型,则不会被捕获
    print('catch the exception')

异常类的继承层次

BaseException   											#所有异常的基类
 +-- SystemExit												# 解释器请求退出
 +-- KeyboardInterrupt    						# 用户中断执行(通常是输入^C)
 +-- GeneratorExit										# 生成器(generator)发生异常来通知退出
 +-- Exception												# 常规错误的基类
      +-- StopIteration								# 迭代器没有更多的值
      +-- StopAsyncIteration					# 由异步迭代的`__anext__()`抛出的异常
      +-- ArithmeticError							# 所有数值计算错误的基类
      |    +-- FloatingPointError			# 浮点计算错误
      |    +-- OverflowError					# 数值运算超出最大限制
      |    +-- ZeroDivisionError      # 除0异常
      +-- AssertionError							# 断言语句失败
      +-- AttributeError							# 对象没有这个属性
      +-- BufferError									# 缓存错误
      +-- EOFError										# 没有内建输入,到达EOF 标记
      +-- ImportError									# 导入模块/对象失败
      |    +-- ModuleNotFoundError		# 模块不存在
      +-- LookupError									# 无效数据查询的基类
      |    +-- IndexError							# 序列中没有此索引(index)
      |    +-- KeyError								# 映射中没有这个键
      +-- MemoryError									# 内存溢出错误(对于Python 解释器不是致命的)
      +-- NameError										# 未声明/初始化对象 (没有属性)
      |    +-- UnboundLocalError			# 访问未初始化的本地变量
      +-- OSError											# 操作系统错误
      |    +-- BlockingIOError				# 调用阻塞异常错误
      |    +-- ChildProcessError			# 子进程异常
      |    +-- ConnectionError				# 连接异常基类
      |    |    +-- BrokenPipeError		# 管道读写异常
      |    |    +-- ConnectionAbortedError		# 连接失败
      |    |    +-- ConnectionRefusedError		# 连接拒绝
      |    |    +-- ConnectionResetError			# 连接重置
      |    +-- FileExistsError				# 文件已经存在异常
      |    +-- FileNotFoundError			# 文件未找到异常
      |    +-- InterruptedError				# 中断异常
      |    +-- IsADirectoryError			# 文件操作用在目录上
      |    +-- NotADirectoryError			# 不是目录异常
      |    +-- PermissionError				# 权限异常
      |    +-- ProcessLookupError			# 进程不存在异常
      |    +-- TimeoutError						# 超时异常
      +-- ReferenceError							# 试图访问已经垃圾回收了的对象
      +-- RuntimeError								# 一般的运行时错误
      |    +-- NotImplementedError		# 尚未实现的方法
      |    +-- RecursionError					# 超出最大递归深度
      +-- SyntaxError									# Python 语法错误
      |    +-- IndentationError				# 缩进错误
      |         +-- TabError					# Tab 和空格混用
      +-- SystemError									# 一般的解释器系统错误
      +-- TypeError										# 对类型无效的操作
      +-- ValueError									# 传入无效的参数
      |    +-- UnicodeError						# Unicode 相关的错误基类
      |         +-- UnicodeDecodeError	# Unicode 解码时的错误
      |         +-- UnicodeEncodeError	# Unicode 编码时错误
      |         +-- UnicodeTranslateError	# Unicode 转换时错误
      +-- Warning											# 警告的基类
           +-- DeprecationWarning			# 关于被弃用的特征的警告
           +-- PendingDeprecationWarning		# 关于特性将会被废弃的警告
           +-- RuntimeWarning					# 可疑的运行时行为(runtime behavior)的警告
           +-- SyntaxWarning					# 可疑的语法的警告
           +-- UserWarning						# 用户代码生成的警告
           +-- FutureWarning					# 关于构造将来语义会有改变的警告
           +-- ImportWarning					# 导入警告
           +-- UnicodeWarning					# unicode相关警告
           +-- BytesWarning						# 字节相关警告
           +-- ResourceWarning				# 资源使用情况警告

示例:

import sys

try:
    sys.exit(1)
except SystemExit:   # 使用SystemExit捕获异常
    print('catch the exception')

print('outer')

多异常捕获

except可以捕获多个异常

try:
    a = 1/0
except ZeroDivisionError:
    print('1/0')
except Exception:
    print('Exception')

捕获规则:

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

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

如果任何一个except都没有捕获到这个异常,则该异常直接抛出

捕获原则:

从小到大,从具体到宽泛

as子句

被抛出的异常,是异常的示例,可以使用as子句获得这个对象

try:
    a = 1/0
except ZeroDivisionError as e:  # 使用e获得对象
    print(e)
except Exception as e :
    print(e)

finally子句

在try...except语句块中,不管是否发生了异常,都会执行finally子句

f = None
try:
    f = open('text.txt')
except FileNotFoundError as e:
    print('{} {} {}'.format(e.__class__, e.errno, e.strerror))
finally:    # 无论如何都会执行f的关闭操作
    print('clear work')
    if f:
        f.close()

也可以在finally中再次捕捉异常

f = None
try:
    f = open('text.txt')
except FileNotFoundError as e:
    print('{} {} {}'.format(e.__class__, e.errno, e.strerror))
finally:
    print('clear work')
    try:
        f.close()
    except Exception as e:
        print(e)

异常的传递

异常总是向外层抛出,如果外层没有处理这个异常,就会继续向外抛出,如果内层捕获并处理了异常,外部就不能捕获到了,如果最外层还是没有处理,就会中断异常所在的线程

try:
    try:
        ret = 1/0
    except KeyError as e:  # 未能捕获异常
        print(e)
    finally:
        print('inner finally')
except:
    print('outer catch')
finally:
    print('outer finally')
    
inner finally
outer catch
outer finally

else子句

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

try:
    ret = 1 * 0
except ArithmeticError as e:
    print(e)
else:
    print('ok')
finally:
    print('finally')

总结

try:
  <语句>   # 运行代码
except <异常类>:
  <语句>   # 捕获某种类型异常
except <异常类> as <变量名>:
  <语句>     # 捕获某种类型的异常并获得对象
else:      # 如果没有异常发生执行
  <语句>
finally:     # 退出try总会执行
  <语句>

try工作原理

  • 如果try语句中执行时发生异常,搜索except子句,并执行第一个匹配该异常的except子句。
  • 如果try中语句执行时发生异常,但没有匹配的except子句,则异常会递交给外层try,如果外层也没有处理这个异常,则继续向外传递,如果都不处理,就终止异常所在的线程。
  • 如果在try执行时没有发生异常,将执行else子句中的语句。
  • 无论try中是否发生异常,finally子句最终都会执行。
posted @ 2021-07-14 11:23  勤俭持家亮公子  阅读(262)  评论(0)    收藏  举报