跳转至

异常处理

参考链接: https://zhuanlan.zhihu.com/p/109340070

什么是异常?

异常是程序发生 错误 的信号, 程序一旦出现错误, 便会产生一个异常.
若程序中没有处理它, 就会抛出该异常, 程序的运行也随之终止.

错误分为两种:
1> 语法上的错误SyntaxError, 这种错误应该在程序运行前就修改正确
2> 逻辑错误. eg: TypeError、ValueError、NameError等

# -- TypeError: 数字类型无法与字符串类型相加
1+2

# -- ValueError: 当字符串包含有非数字的值时,无法转成int类型
num=input(">>: ") # -- 输入hello
int(num)

# -- NameError: 引用了一个不存在的名字x
x

# -- IndexError: 索引超出列表的限制
l=['egon','aa']
l[3]

# -- KeyError: 引用了一个不存在的key
dic={'name':'egon'}
dic['age']

# -- AttributeError: 引用的属性不存在
class Foo:
    pass
Foo.x

# -- ZeroDivisionError: 除数不能为0
1/0

若错误发生的条件是“可预知的”, 我们应该用 if 来进行 ”预防”;
若错误发生的条件“不可预知”, 即异常一定会触发, 那么我们才应该使用 try...except 语句来处理.


异常处理

try:
    被检测的代码块
except NameError:
    触发NameError时对应的处理逻辑
except (IndexError,TypeError):
    触发IndexError时对应的处理逻辑
except Exception: # -- 万能异常
    其他类型的异常统一用此处的逻辑处理
else:
    在被监测的代码块没有异常发生时会自动执行
finally: 
    # -- 通常在finally的子代码块做一些回收资源的操作,比如关闭打开的文件、关闭数据库连接等
    被监测的代码块无论有无异常都会自动执行

本来程序一旦出现异常就会终止运行, 有了异常处理以后.
在被检测的代码块出现异常时, 被检测的代码块 中异常发生位置之后的代码将不会执行.
取而代之的是 执行匹配异常的except子代码块, 其余代码均正常运行.


raise与assert

raise由程序员自己来明确地触发异常
断言语句assert expression, 断定表达式expression成立, 否则触发异常AssertionError

class Student:
    def __init__(self,name,age):
        if not isinstance(name,str):
            raise TypeError('name must be str')
        if not isinstance(age,int):
            raise TypeError('age must be int')

        self.name=name
        self.age=age

stu1=Student(4573,18)

raise与assert

age = '18'

# -- 若表达式isinstance(age,int)返回值为False则触发异常AssertionError
assert isinstance(age, int)

# -- 等同于
if not isinstance(age, int):
    raise AssertionError

自定义异常

在内置异常不够用的情况下, 我们可以通过继承内置的异常类来自定义异常类

class PoolEmptyError(Exception):  # -- 可以通过继承Exception来定义一个全新的异常

    def __init__(self, value='The proxy source is exhausted'):  # 可以定制初始化方法
        super(PoolEmptyError, self).__init__()
        self.value = value

    def __str__(self):  # -- 可以定义该方法用来定制触发异常时打印异常值的格式
        return '< %s >' % self.value


class NetworkIOError(IOError):  # -- 也可以在特定异常的基础上扩展一个相关的异常
    pass


raise PoolEmptyError  # __main__.PoolEmptyError: < The proxy source is exhausted >
# raise NetworkIOError('连接被拒绝')  # __main__.NetworkIOError: 连接被拒绝