掉进悬崖的小白,学习python异常处理,做简单总结(附自定义异常小例题)。

掉进悬崖的小白,学习python异常处理,做简单总结

什么是异常?

异常实际上是程序中错误导致中断了正常的指令流的一种事件.

和传统的方法比较异常的优点:

1.把错误代码从常规代码中分离出来
2.把错误传播给调用堆栈
3. 按错误类型和错误差别分类
4. 系统提供了对于一些无法预测的错误的捕获和处理

什么情况下使用异常机制?

1.当方法因为自身无法控制的原因而不能完成其任务
文件不存在,网络连接无法建立……
2.处理在引入模块中抛出的异常
3.在大的项目中采用统一的方式处理异常时
如编写一个文字处理器
4.异常应该是不经常发生但却可能发生的故障
一定发生的事件不应该用异常机制来处理
5.异常处理用于使系统从故障中恢复
提示信息/不产生无效的结果/释放资源

注意事项:
1.不同的异常处理策略
关键性应用(处理所有异常)
实验软件(可以忽略许多异常)
2.终止程序会导致资源泄漏,利用异常处理释放资源
3.尽可能近地处理异常,这样程序清晰易读
4.能在局部处理的错误不要使用异常机制
异常机制的处理比正常处理效率低

处理机制

捕获并处理异常
try:
# 接受监视的程序块,在此区域内发生的异常,由except中指定的程序处理
#不能有其它语句分隔
except 要处理的异常种类1 as 标识符1:
# 处理异常
except 要处理的异常种类2 as 标识符2:
# 处理异常

或者
except (异常种类1, 异常种类2…) as 标识符…:
# 处理异常
或者
except:
# 上面未捕获的处理异常
else:
# 未监视到异常时执行的代码
finally:
# 有无异常均会执行的代码

try语句:异常监视块

作用:监视该代码块是否有异常发生,若有异常,产生异常对象并抛出

except语句:异常处理代码块

作用:捕捉try语句中抛出的异常,并按照代码块中的语句处理

格式:标识符主要用于解析异常对象
except 要处理的异常种类 as 标识符:
except (异常种类1, 异常种类2…) as 标识符…:

注意:

1.每个try语句必须伴随1-n个except语句
2.异常总是由距离产生异常最近的匹配except代码段处理
3.try-except可以嵌套使用
4.匹配的except执行完毕后,同级的except将被忽略
5.先except小的再except老的
6.整个执行流程中若无except处理 程序中断!
7.except的类型应尽量精确
8.请注意你调用的方法是否有可能抛出异常
9.except中也可能产生异常 会抛给嵌套的上一级处理
10.永远不要except中吞掉异常,否则在系统发生异常时,你永远不知道到底发生了什么:
推荐:
except BaseException:
# 处理异常的语句
raise #再次将异常抛出
11.try-except机制不该被用于流程控制,异常情形应该是很稀少的,而不是经常性的

else

等同于for…else和while…else
在不发生异常时执行的语句块

一定会执行的程序块—finally

异常处理的统一出口
finally:
# 不论发生什么异常(或者不发生任何异常),都要执行的部分;
finally:
1.捕获异常的最后一步是通过finally语句为异常处理提供一个统一的出口,使得在控制流程转到程序的其他部分以前,能够对程序的状态作统一的管理。
2.无论try所指定的程序块中是否抛出异常,也无论except语句的异常类型是否与所抛弃的异常的类型一致,finally所指定的代码都要被执行,它提供了统一的出口。
3.通常在finally语句中可以进行资源的清除工作,如关闭打开的文件、删除临时文件等。

finally和return的关系:
1.当try和except中有return时,finally仍然会执行;
2.finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,不管finally中的代码如何修改,返回的值都不会改变,仍然是之前保存的值),所以函数返回值是在finally执行前确定的;

异常分类

  • BaseException # 所有异常的父类
    • SystemExit # 由sys.exit()抛出的异常
    • KeyBoardInterrupt # 通常由ctrl+c或者Delete抛出的异常
    • GeneratorExit # 生成器(generator)发生异常来通知退出
    • Exception # 常规异常基类
      • StopIteration # 迭代器没有更多的值
      • StopAsyncIteration # 由异步迭代的__anext__()抛出的异常
      • ArithmeticError # 各种算数错误引起的异常
        • FloatingPointError # 浮点数操作错误
        • OverflowError # 结果超出范围
        • ZeroDivisionError # 0为除数异常
    • AssertionError # assert错误异常
    • AttributeError # 属性引用异常
    • BufferError # 缓存错误
    • EOFError # 读不到数据
    • ImportError # import错误
      • ModuleNotFoundError # 找不到模块
    • LookupError # 由索引和key值引起的异常
      • IndexError # 索引错误
      • KeyError # 字典key值错误
    • MemortError # 内存溢出异常
    • NameError # 本地和全局找不到变量名
      • UnboundLocalError # 局部变量没有赋值
    • OSError # system错误
      • BlockingIOError # 调用阻塞异常错误
      • ChildProcessError # 子进程
      • ConnectionError # 连接
        • BrokenPipeError # 管道读写异常
        • ConnectionAbortedError # 连接失败
        • ConnectionRefusedError # 连接拒绝
        • ConnectionResetError # 连接重置
      • FileExistsError # 创建文件和文件夹错误
      • FileNotFoundError # 文件未找到
      • InterruptedError # 中断错误
      • IsADirectoryError # 文件操作用在文件夹上
      • NotADirectoryError # 不是文件夹
      • PermissionError # 权限
      • ProcessLookupError # 进程不存在
      • TimeoutError # 超时
    • ReferenceError # 试图访问已经垃圾回收的对象异常
    • RuntimeError #
      • NotImplementedError # 未实现抽象方法异常
      • RecursionError # 超出最大递归深度
    • SyntaxError # 语法错误
      • IndentationError # 缩进错误
        • TabError # Tab 和空格混用
    • SystemError # 解释器中断
    • TypeError # 对类型无效的操作
    • ValueError # 赋值错误
      • UnicodeError # Unicode 相关的错误
        • UnicodeEncodeError # unicode编码错误
        • UnicodeDecodeError # unicode解码错误
        • UnicodeTranslateError # unicode转换错误
    • Warning # 警告的基类
      • DeprecationWarning # 关于被弃用的特征的警告
      • PendingDeprecationWarning # 表明此操作将来会被弃用
      • UserWarning # 用户代码生成的警告
      • SyntaxWarning # 可疑的语法的警告
      • RuntimeWarning # 可疑的运行时行为警告
      • FutureWarning # 关于构造将来语义会有改变的警告
      • ImportWarning # 导入警告
      • UnicodeWarning # unicode相关警告
      • BytesWarning # 字节相关警告
      • ResourceWarning # 资源使用情况警告

手动抛出异常

手动抛出异常的方法:raise 空|异常对象
注意:
单raise时,会将当前捕获的异常直接再次抛出

raise exception_obj;
抛出异常: 不是出错产生,而是人为地抛出

1.任何从BaseException派生的类都可以用raise语句抛出,抛出异常用来表明程序遇到的错误无法正常执行而需要异常处理
raise BaseException(“some infomation”);
2.异常抛出点后的代码在抛出异常后不再执行
也可以说异常的抛出终止了代码段的执行

自定义异常

异常是一个类,用户定义的异常一般继承自Exception:
‘’‘自定义的异常类’’’
来个例题:

# 在定义银行类时,若取钱数大于余额则作为异常处理
# (InsufficientFundsException).
# 思路:产生异常的条件是余额少于取额,  因此是否抛出异常
# 要判断条件
# 取钱是Withdrawal 方法中定义的动作,因此在该方法中产生
# 异常.
# 处理异常安排在调用Withdrawal 的时候,因此Withdrawal
# 方法要声明异常,由上级方法调用
# 要定义好自己的异常类
# 要求:捕捉到的异常对象内有余额和取额的信息

class GetmoneyError(Exception):

    def __init__(self, acc, get_money) -> None:
        super().__init__()
        self.acc = acc
        self.get_money = get_money

    def __str__(self) -> str:
        return f"异常发生的账户是{self.acc.acc_id}," \
            f"情况为取款金额{self.get_money},超出账户余额{self.acc.money}"


class Account:

    def __init__(self, acc_id, money) -> None:
        super().__init__()
        self.acc_id = acc_id
        self.money = money

    def withdraw(self, get_money):
        if 0 < get_money < self.money:
            return get_money
        else:
            # print("余额不足")
            # pass
            raise GetmoneyError(self, get_money)


if __name__ == '__main__':
    try:
        acc = Account("001", 123)
        acc.withdraw(244)
    except GetmoneyError as e:
        print(e)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章