目录

Python面向对象(5)异常

Python面向对象(5)异常

学习目标

  • 了解异常
  • 捕获指定异常
  • 异常的else
  • 异常的finally
  • 异常的传递
  • 自定义异常

了解异常

当检测到一个错误时,解释器就无法继续执行,反而出现了一些错误的提示,这就是所谓的"异常”,例如以r的文件模式打开一个不存在的文件open('test.txt', 'r')会报"no such file or directory"的错误,程序就不会继续执行。

使用异常可以解决这种问题,不确定某代码是否会出错,则可以放到异常中,异常则尝试执行该语句,万一有错误,可以执行没有错误的代码来替代该代码,则程序不会报错,且不会停止执行。

异常的写法

1
2
3
4
try:
    # 可能发生错误的代码
except:
    # 如果发生异常则执行的代码

需求:尝试以r文件模式打开一个文件,但是这个文件不知道存不存在,不存在以w模式打开

1
2
3
4
try:
    f = open('ss.txt','r')	# 发生了错误,则抛出异常给except
except:
    f = open('ss.txt','w')

捕获指定异常

逻辑:用try来对不确定是否发生错误的语句抛出异常,用except来捕获指定类型的异常并执行其操作。

Python中内置异常的常见类型:

异常类型 说明
NameError 访问一个未声明的变量,变量未定义会引发NameError异常
ZeroDivisionError 当除数为零的时候,会引发ZeoDioenorr异常
SyntaxError 解释器发现语法错误时,会引发SyntaxError异常
IndexError 使用序列中不存在的索引时,会引发IndexErr异常
KeyError 字典中不存在的键访问值时,会引发KeyError异常
FileNotFoundError 试图打开不存在的文件时,会引发FileNotFoundError异常
AttributeError 当尝试访问未知的对象属性时,会引发AttributeError异常

捕获异常的代码为:

1
2
3
4
try:
    可能发生错误的代码,如发生错误则抛异常给except
except 指定异常类型:
    如果捕获到该异常类型执行的代码

体验一下:

1
2
3
4
5
6
7
8
9
try:
    print(a)
except NameError:# 如果try中代码和异常类型一致,则执行该代码
    print('没有定义')
    
try:
    print(1/0)
except NameError:# 不一致则报错
    print('没有定义')

⚠️注意:

  1. 如果尝试执行的代码异常类型和要捕获的异常类型不一致,则无法捕获异常,既无法执行except下方的代码;
  2. 一般try中只放一行尝试执行的代码。

捕获多个异常

当捕获多个异常时,可以把要捕获异常类型的名字放入元组放在except后。

1
2
3
4
try:
    print(1/0)
except(NameError,ZeroDivisionError):
    print('try中代码有错误,异常捕获成功')  #try中代码有错误,异常捕获成功

捕获异常描述信息

异常描述信息就是在代码报错时,在异常类型:之后的说明文字即为异常描述信息。异常描述信息提供了代码错误的详细信息,我们可以将其捕获保存存储起来。

将捕获到的异常描述获取出来需要使用as关键字:

1
2
3
4
try:
    print(1/0)
except(NameError,ZeroDivisionError) as result:
    print(result)

捕获所有异常

Exception是所有程序异常类的父类,捕获父类即可以捕获满足其异常类型的子类,则无需提前判断。

1
2
3
4
try:
    print(aaa)
except Exception as result:
    print(result)			# name 'aaa' is not defined

异常的else

else指如果try中代码没有异常,则需要执行的代码,和循环中的else在没有中断退出正常执行完成后需要执行一样。

1
2
3
4
5
6
7
try:
    print(aaa)                  # 1
except Exception as result:
    print(result)               # 2
else:
    print('没有异常则执行此句')     # 3
# 如果1没有异常则执行1和3,如果1有异常则只执行2,这里只执行2

异常的finally

关键字finally表示的是无论是否异常都要执行的代码,例如关闭文件。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
try:
    f = open('1.txt', 'r')      # 1
except Exception as result:
    f = open('1.txt', 'w')      # 2
else:
    print('r模式没有异常')        # 3
finally:
    print('无论如何都执行这句话')  # 4
    f.close()
# 如果1没有异常执行1和3、4; 如果1有异常,执行2,4

异常的传递

先体验一下异常的传递,异常传递通俗理解为异常的嵌套书写。

需求:

  1. 尝试只读方式打开test.txt文件,如果文件存在则读取文件内容,文件不存在则提示用户即可。
  2. 读取文件内容要求:尝试循环读出内容,读取过程中如果检测到用户意外终止程序,则except捕获异常并提示用户。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import time
try:    # 如果正常打开则打开,如果文件不存在则抛出异常
    f = open('test.txt')
    try:        # 如果正常打开就执行文件读取,如果意外终止则抛出异常
        while True:
            content = f.readline() # 逐行获取内容
            if content == '':
                break
            print(content)
            time.sleep(3)
    except:	# 捕获意外终止的异常
        print('读取意外终止')
    finally:
        f.close()
except:	# 捕获文件不存在的异常
    print('文件不存在')

自定义异常

在Python中,抛出自定义异常的语法为raise 异常子类对象

自定义异常的作用就是用来将不满足程序逻辑的情况进行一个反馈,反馈给用户,对于将不符合程序逻辑要求的错误进行提示,区别于Python中内置的异常,这里的异常不是程序代码错误,而只是业务逻辑不合要求。

需求:密码长度不足,则报异常(用户输入密码,如果输入的长度不足3位,则报错,即抛出自定义异常描述,并捕获该异常)

首先须要定义这个密码长度不足的异常,抛出自定义异常的的异常描述,最后我们写程序来捕获该异常。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# 自定义异常类
class ShortInputError(Exception):   # 继承Exception父类
    def __init__(self, length, min_len):
        self.length = length  #     用户输入的长度
        self.min_len = min_len      # 以后可以变更的最小长度

    def __str__(self):
        return f'您输入的长度是{self.length}, 请至少输入{self.min_len}个字符长度'
# 抛出并捕获异常
def main():
    try:
        con = input("请输入密码:")
        if len(con) < 3:
            raise ShortInputError(len(con),3) # 对象传入两个初始化参数
    except Exception as e:
        print(e)
    else:
        print('输入完成!',)
main()

总结

  • 异常的作用就是为了避免程序中不确定语句导致的错误而使整个程序中断报错,而提供的一种稳定的处理方式,将不确定语句写入try中尝试执行,报错则执行except语句中的内容,避免程序整个的中断。
  • 捕获指定异常指的是在异常发生时,try中语句发生与except语句中异常类型相符合的异常,则进行捕获(常用的异常类型有七种),从而进行特定的操作;捕获多个异常则是将多个异常类型组合为一个元组写入except语句中,对try中语句进行特定捕获。
  • 当捕获异常的类型不确定,我们可以捕获所有异常的父类Exception类进行所有异常的捕获。
  • 异常的描述信息指的是在异常发生时的详细解释,我们可以将其在用 except 异常类型 as 变量保存起来。
  • 异常的else指的是在异常语句中,如果try中异常没有发生,即执行的代码,如果异常发生则不执行。
  • 异常的finally指的是在异常语句中,无论try中异常是否发生,均执行的代码。
  • 异常的传递一般指的是在异常中进行异常嵌套,即在尝试代码或者执行异常发生代码中进行其他异常的尝试。
  • 自定义异常指的是我们可以把程序的逻辑错误(非Python内置异常)定义为一个异常,例如:密码输入长度不够规定定义为一个异常,将其写在Exception子类中,在try语句中进行raise 异常子类对象的抛出,由except接收并完成其操作。