Python基础 --【异常】

139 阅读6分钟

1、异常概念

程序运行时,如果Python解释器遇到一个错误,会停止程序的执行并且提示一些错误信息,这就是异常

2、捕获异常

① 简单的异常处理

语法格式

try:
    可能发生错误的代码
except:
    如果出现异常执行的代码

示例:

需求:要求用户输入整数

try:
    num = int(input("请输入一个整数"))
    print("输入整数有效!")
except:
    print("请输入正确的整数!")

当用户输入整数时,能被int转换时会执行try中的代码块

请输入一个整数:10
输入整数有效!

当用户输入不是整数时,不能被int转换时会执行except中的代码块

请输入一个整数:abc
请输入正确的整数!

通过结果说明:使用try来尝试执行后面语句块中的代码,如果代码发生异常问题,那么异常信息就会被except捕捉到,可以在except后面进行异常处理,如果代码没有异常,那么程序就正常运行,不会执行except后的代码。

② 捕捉指定异常类型

在程序执行时,可能会遇到不同类型的异常,并且需要针对不同类型的异常做出不同的响应,这个时候就需要捕获错误类型了。

当Python解释器抛出异常时,最后一行错误信息的第一个单词就是错误类型

image.png

语法格式

第一种:捕捉指定单个错误类型

try:
    尝试执行的代码
except 错误类型1:
    针对错误类型1,做出相应的代码处理

第二种:捕捉指定多个错误类型(将多个异常通过圆括号包裹成一个元组)

try:
    尝试执行的代码
except (错误类型1,错误类型2,错误类型3……):
    针对错误类型123……,做出相应的代码处理

第三种:异常别名--获取异常信息

try:
    尝试执行的代码
except (错误类型1,错误类型2,错误类型3……)as e:
    print(e)
    当异常发生时,处理异常的代码

示例:

需求:提示用户输入一个整数,使用8除以用户输入的整数并输出

    num = int(input("请输入一个整数"))
    result = 8 / num
    print(result)

输入的值不同,错误提示不同:

1)当输入字母时提示:值错误的异常

image.png

2)当输入数字0时,因为分母不能为0,提示:除0错误异常

image.png

针对两种不同的错误类型分别给用户不同的提示代码:

try:
    num = int(input("请输入一个整数:"))
    result = 8 / num
    print(result)
except ValueError:
    print("请输入正确的整数")
except ZeroDivisionError:
    print("除0错误")

当用户输入字母时,执行的结果

请输入一个整数:abc
请输入正确的整数

当用户输入0时,执行的结果

请输入一个整数:00错误

③ 捕获所有异常

如果异常的种类不确定,则可以使用exception来指代所有种类的异常。

语法格式

try:
    pass
except Exception as e:
    print(e)

示例

try:
    num = int(input("请输入一个整数:"))
    result = 8 / num
    print(result)
except ValueError:
    print("请输入正确的整数")
except Exception as e:
    print("未知错误 %s"%e)

当输入0时

请输入一个整数:0
未知错误division by zero

3.异常的传递性

  • 当代码出现了多层级的调用时,在其中发生了异常,如果没有处理这个异常,这个异常会自动向上抛出
  • 如果上层也没有处理,那么再继续向上抛出,直到抛到解释器,解释器默认处理异常的方式就是中断程序,将异常信息显示控制台上

示例

# 异常的传递
def func_a():
    print('Func a run ...')
    func_b()

def func_b():
    print("Func b run ...")
    func_c()

def func_c():
    print('Func c run ...')
    print(1 / 0)

func_a()

运行

image.png 解决方法

① 可以在抛异常的代码中处理异常

def func_a():
    print('Func a run ...')
    func_b()

def func_b():
    print("Func b run ...")
    func_c()

def func_c():
    print('Func c run ...')
    try:
        print(1 / 0)
    except Exception:
        print("除数不能为零!")
        
func_a()

运行结果

image.png

② 因为异常具有传递性,可以在调用的代码中处理异常

def func_a():
    print('Func a run ...')
    func_b()

def func_b():
    print("Func b run ...")
    try:
        func_c()
    except Exception:
        print("除数不能为零!")

def func_c():
    print('Func c run ...')
    print(1 / 0)

func_a()

运行结果 image.png

4.异常捕获中else和finally语句

  • else表示的是没有异常要执行的代码
  • finally表示无论是否发生异常都要执行的代码

示例

try:
    f = None  #如果不加这段代码会报变量不存在异常
    f = open('b.txt','r')
except Exception as e:
    print('要打开的文件不存在')
    print(e)
else:
    # 对文件的读取操作
    print('else 是当没有出现异常时,执行的else语句 块')
    print(f.read())
finally:
    # 不管是否出现异常,都要执行这个语句块
    # 一般这个模块中,主要写的内容 是资料关闭或回收
    # 比如,文件的关闭,网络连接的关闭,数据库的关闭
    print('无论是否出现异常,都会执行finally语句 块')
    if f != None:
        f.close()

运行结果(b.txt文件不存在)

image.png

5.语法糖

用with替代try-except

with open('a.txt','r') as f:
    f.read()

6.自定义异常和抛出异常

所有异常都直接或间接继承Exception这个父类

语法格式

第一种:

class 异常名Error(Exception):
    pass

第二种:

class 异常名Error(Exception):
    def __init__(self,msg):
        self.__msg = msg
       
    def __str__(self):
        return self.__msg

示例

新建自定义模块a.py (自定义异常是从开发者角度)

# 定义一个用来判断当前手机号是否有非法字符的异常
class PhoneNumberNotDigitError(Exception):
    pass
    
# 定义一个用来判断手机号位数是否合法的异常
class PhoneNumberLengthError(Exception):
    def __init__(self,msg):
        self.__msg = msg
       
    def __str__(self):
        return self.__msg
        
# 定义一个函数,用来获取一个电话号码
def get_phone_number():
    pn = input("请输入一个11位的手机号:")
    if pn.isdigit() == False:
        # 抛出自定义的异常
        raise PhoneNumberNotDigitError()
    elif len(pn) != 11:
        raise PhoneNumberLengthError("手机号位数不正确")
    return "输入的手机号是合法的:"+pn

导入a.py模块

from a import *

get_phone_number()

运行结果

1)当输入手机号位数不正确时,抛出自定义PhoneNumberLengthError异常

image.png 2)当输入手机号不是纯数字时,抛出自定义PhoneNumberNotDigitError异常

image.png

解决自定义异常

from a import *
try:
    num = get_phone_number()
# 或者直接写except Exception as e
except(PhoneNumberNotDigitError,PhoneNumberLengthError) as e:
    print(e)
else:
    print(num)

运行结果 1)当输入号码正确时

image.png

2)当输入的号码不正确时 image.png

3)当输入的号码不是11位时 image.png