Python异常处理知识点

一、异常处理概念

1. 什么是异常*

异常是错误发生的信号,程序出错就会产生异常

2. 为什么要处理异常*

为了保证程序的稳定性与容错性,也就是在遇到错误时程序不会崩溃。

3. 异常的三个组成*

1.发生异常的地方\位置
2.异常的种类
3.异常信息\原因

4. 语法错误应什么时候处理*

语法错误是过不了Python解释器的审核的,必须在程序执行前修正好,否者执行不了。

5. 逻辑错误正确解决方法*

分两种可预知,和不可预知;
可预知可应用if判断等方法规避;
不可预知可用try..except...在程序发生错误后进行处理

6. 异常处理的完整语法*

try:
    代码块
except 异常类型 as f: # f接受异常信息  PS:as 句柄 可省略
    print(f) # 打印异常信息
finally:
    代码块 
    无论上层是否抛异常都会执行,
    一般用来进行清理操作,
    如关闭文件,关闭数据库等等	    	   

7. 常用的异常种类

AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的

二、异常处理多种使用场景及语法的使用方式

1. 多分支处理异常

使用场景:

当被检测的代码块中有可能触发不同类型的异常时,
针对不同类型的异常,如果我们想分别用不同的逻辑处理,需要使用到多分支的except
try:
    被检测的代码块
except NameError:
    触发NameError时对应的处理逻辑
except IndexError:
    触发IndexError时对应的处理逻辑
except KeyError:
    触发KeyError时对应的处理逻辑

释:类似于多分支的elif,从上到下依次匹配,匹配成功一次便不再匹配其他

2. 多种异常统一用一种逻辑进行处理

可以将多个异常放到一个元组内,用一个except匹配
try:
    被检测的代码块
except (NameError,IndexError,TypeError):
    触发NameError或IndexError或TypeError时对应的处理逻辑

3. 万能异常Exception

使用场景:

想捕获所有异常并用一种逻辑处理;
try:
    被检测的代码块
except NameError:
    触发NameError时对应的处理逻辑
except IndexError:
    触发IndexError时对应的处理逻辑
except Exception:
    其他类型的异常统一用此处的逻辑处理

4. 多分支except跟else的使用

else必须跟在except之后,不能单独存在,
只有在被检测的代码块没有触发任何异常的情况下才会执行else的子代码块
try:
    被检测的代码块
except 异常类型1:
    pass
except 异常类型2:
    pass
......
else:
    没有异常发生时执行的代码块

5. finally与try…except…连用解析

语法上讲finally必须放到else之后。
可以使用try...except...finally的形式,
 try: 
     被检测的代码块 
 except 异常类型1: 
     pass 
 except 异常类型2: 
     pass 
 ...... 
 else: 
     没有异常发生时执行的代码块 
 finally: 
     无论有无异常发生都会执行的代码块
也可以直接使用try...finally的形式,如下
try:
    代码块
finally:
    代码块
无论被检测的代码块是否触发异常,都会执行finally的子代码块,
因此通常在finally的子代码块做一些回收资源的操作,
比如关闭打开的文件、关闭数据库连接等

三、异常处理中raise的使用*

用于主动触发异常,还可自定义异常

使用场景:

在不符合Python解释器的语法或逻辑规则时,
是由Python解释器主动触发的各种类型的异常,而对于违反程序员自定制的各类规则,
则需要由程序员自己来明确地触发异常,这就用到了raise语句,
raise后必须是一个异常的类或者是异常的实例;

1. 主动触发异常*

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) # TypeError: name must be str
stu2=Student('sailan','18') # TypeError: age must be int

2. 自定义异常及输出格式*

class Interface(BaseException):
    def __init__(self, msg, x, y, z):
        self.msg = msg
        self.x = x
        self.y = y
        self.z = z

    def __str__(self):
        return "<%s:%s:%s:%s>" % (self.msg,self.x,self.y,self.z)

	
raise Interface("接口异常", 11, 22, 33) # 调用类,进行定义异常内容
# 触发异常,打印异常信息,会导致上面__str__方法的执行,从而达到自定义异常信息的效果

异常信息
    raise Interface("接口异常", 11, 22, 33)
__main__.Interface: <接口异常:11:22:33>

3. 断言assert

使用场景:
多用于测试,用来判断了解程序运行状态等等,断言成功正常执行后续代码,出错则抛出AssertionError,断言的使用应不影响程序代码格局;

salaries=[1.1,2.2]

# if len(salaries) != 3: # 断言效果可以用多种方式实现,使用assert关键字更方便
#     raise NameError


assert len(salaries) == 3 # 成功则正常运行后续代码 和上面注释的方法效果一样

print(salaries[2])

四、何时使用异常处理

try...except是我们附加给程序的一种异常处理的逻辑,与主要的工作逻辑是没关系的,
这种东西加的多了,会导致代码可读性变差,异常处理不应滥用,
我们应尽量写好代码逻辑,只有在错误发生的条件无法预知的情况下,
才应该加上try...except

猜你喜欢

转载自blog.csdn.net/msmso/article/details/108109675