Python基础学习笔记——异常

一、bug的简介

  1947年,世界第一部万用计算机的进化版——马克2号Mark II)的程序运行发生了异常,计算机程序之母格蕾丝经调试后,发现是一只飞蛾卡在了继电器触点中间,于是她把虫子的尸体
粘在了自己的工作日记上,称它们为臭虫bug)。

  从此以后,计算机程序或硬件系统中存在的错误、故障、缺陷或漏洞,统称为bug。调试程序的步骤,也称为debug

  当bug导致程序跳出运行时,系统会报出对应的异常类型Python中常见的异常有:语法格式错误SyntaxError值类型错误ValueError空索引错误IndexError空键错误KeyError未声明错误NameError未分配错误AttributeError除零错误ZeroDivisionError,……


二、异常捕获预处理机制

1. 继承

  Python中,异常也是对象,所有内置的异常类都是从BaseException继承,且都在内建模块builtins中定义。在捕获异常时,匹配的是其对应的异常类及其父类。继承层次如下:

BaseException  # 所有异常的基类
 +-- SystemExit  		# 解释器请求退出
 +-- KeyboardInterrupt  # 用户中断执行(Ctrl+C)
 +-- GeneratorExit  	# 生成器异常退出
 +-- Exception  		# 常规异常的基类
      +-- StopIteration  		# 迭代器没有更多的值
      +-- StopAsyncIteration  	# 必须通过异步迭代器对象的__anext__()方法引发以停止迭代
      +-- ArithmeticError  		# 算术错误异常的基类
      |    +-- FloatingPointError  	# 浮点计算错误
      |    +-- OverflowError  		# 溢位错误(数值太大)
      |    +-- ZeroDivisionError  	# 除(模)零 
      +-- AssertionError  	# 断言失败
      +-- AttributeError  	# 属性/方法的引用或赋值失败
      +-- BufferError  		# 缓冲区错误
      +-- EOFError  		# 当input()函数在未读取任何数据时达到文件结束条件(EOF)时引发
      +-- ImportError  		# 导入模块/对象失败
      |    +-- ModuleNotFoundError  # 寻找模块失败
      +-- LookupError  	# 无效键/索引时的基类
      |    +-- IndexError  	# 序列无此索引
      |    +-- KeyError  	# 映射无此键
      +-- MemoryError  	# 内存溢出错误
      +-- NameError  	# 对象未声明/初始化 
      |    +-- UnboundLocalError  	# 本地变量未初始化
      +-- OSError  		# 操作系统错误
      |    +-- BlockingIOError  	# 操作将阻塞对象(e.g.socket)设置为非阻塞操作
      |    +-- ChildProcessError  	# 子进程操作失败
      |    +-- ConnectionError  	# 连接异常的基类
      |    |    +-- BrokenPipeError  		# 在已关闭的管道写入
      |    |    +-- ConnectionAbortedError  # 连接尝试被对等方中止
      |    |    +-- ConnectionRefusedError  # 连接尝试被对等方拒绝
      |    |    +-- ConnectionResetError    # 连接由对等方重置
      |    +-- FileExistsError  	# 创建已存在的文件或目录
      |    +-- FileNotFoundError  	# 请求不存在的文件或目录
      |    +-- InterruptedError  	# 系统调用被输入信号中断
      |    +-- IsADirectoryError  	# 在目录上请求文件操作(e.g.os.remove())
      |    +-- NotADirectoryError  	# 在非目录对象上请求目录操作(e.g.os.listdir())
      |    +-- PermissionError  	# 操作权限不足
      |    +-- ProcessLookupError  	# 给定进程不存在
      |    +-- TimeoutError  		# 系统函数在系统级别超时
      +-- ReferenceError  	# weakref.proxy()函数创建的弱引用试图访问已经垃圾回收了的对象
      +-- RuntimeError  	# 未定义类错误
      |    +-- NotImplementedError  # 在用户定义的基类中,抽象方法要求派生类重写该方法或者正在开发的类指示仍需添加实际实现
      |    +-- RecursionError  		# 超出最大递归深度
      +-- SyntaxError  	# 语法格式错误
      |    +-- IndentationError 	# 缩进错误
      |         +-- TabError  # Tab和空格混用
      +-- SystemError  	# 解释器内部错误
      +-- TypeError  	# 操作或函数应用于不适当类型的对象
      +-- ValueError  	# 操作或函数接收到具有正确类型但值不合适的参数
      |    +-- UnicodeError   # Unicode错误
      |         +-- UnicodeDecodeError  	# Unicode解码错误
      |         +-- UnicodeEncodeError  	# Unicode编码错误
      |         +-- UnicodeTranslateError  	# Unicode转码错误
      +-- Warning  		# 警告的基类
           +-- DeprecationWarning  			# 已弃用功能警告
           +-- PendingDeprecationWarning  	# 不推荐使用功能警告
           +-- RuntimeWarning  				# 可疑行为警告
           +-- SyntaxWarning  				# 可疑语法警告
           +-- UserWarning  				# 用户代码生成警告
           +-- FutureWarning  				# 可能错误警告
           +-- ImportWarning  				# 模块导入警告
           +-- UnicodeWarning  				# Unicode警告
           +-- BytesWarning  				# 与bytes和bytearray相关的警告
           +-- ResourceWarning  			# 资源使用警告(被默认警告过滤器忽略)

2. 捕获与预处理

  try...except...语句用于捕获并处理异常,其机制为:

  try下的代码块运行时,如果发生异常,不跳出程序从上到下依次检索except子句,并执行第一个匹配该异常的except子句。

try:
    n = 1/0		# 发生错误,转到except语句
    print(n)	# 不执行
except SyntaxError or ValueError:	# 异常类型错误
    print('Error')					# 不执行
except ZeroDivisionError:			# 异常类型正确
    print('ZeroDivisionError')		# 打印错误

  若需要对其他所有错误有统一的应对行为,可不设置异常类型,或者将except子句匹配的异常类型设为BaseException。此外,也可以通过as将匹配的异常赋给变量,以便于查询异常发生的具体原因,并防止 “异常字句过于宽泛” 的警告。

try:
    n = m
    print(n)
# 一般是最后一个
except BaseException as E:	# except:(必须是最后一个)
    print(E)				# name 'm' is not defined

3. 嵌套与传递

  try块可以在许多结构中嵌套,包括自身、循环函数等等。在多层嵌套中,异常的传递机制为:
  若异常未被内层except子句捕获,则将被递交到外层try块,直至异常被处理。如果都不处理该异常,就终止其所在线程。

  在此基础上,还有追加子句elsefinally。当没有匹配except子句时,异常就会由else子句捕获,并执行else子块。而不论try块中是否发生异常,finally子句最终都会被执行,并释放本层try块的资源

# 载入精确计算库
from decimal import Decimal
# 初始化循环条件
flag = 1

while flag:
    # 运算器主体
    try:
        # 功能说明
        print('保留三位小数的除法运算器'.center(20))
        # 输入参数
        n = input('被除数:')
        m = input('除数:')
        # 计算结果
        result = '商:{:.3f}'.format(float(Decimal(n) / Decimal(m)))
        
    # 除零错误
    except ZeroDivisionError:
        print('division by zero')
    # 输入类型错误
    except ArithmeticError:
        print('invalid operand type(s)')
    # 无异常,输出结果
    else:
        print(result)
    # 循环控制
    finally:
        try:
            flag = int(input('输入1继续,输入0退出:'))
        except BaseException:
            flag = 0

  以上实例代码实现了一个保留三位小数的除法运算器。其中,finally子句中嵌套了一个内层try块。另外,由于调用了第三方库,大部分发生的相似错误并不属于常规异常子类,可以考虑向其父类追溯

  特别的,包含在循环体函数体的内层try块中的finally子句里,若含有breakreturn语句,那么异常不再发生传递,并且其所在进程将被终止。

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值