跟光磊学Python开发-异常机制 跟光磊学Python开发-异常机制

异常概述

异常指的是不正常,也就是程序在执行过程中发生了不可预知的问题,导致程序崩溃。
Python中常见的异常类如下,它们都直接或者间接继承自位于builtins.py文件中的Exeption类
跟光磊学Python开发-异常机制
跟光磊学Python开发-异常机制

  • NameError
  • TypeError
  • ValueError
  • AttributeError
  • SyntaxError
  • IndexError

异常处理

在日常开发中应该尽量避免异常出现,而程序中可能发生异常的情况,可以通过Pyhton提供的异常处理机制来处理异常,从而提高程序的容错性。

异常处理的语法格式为

try:
		可能发生异常的代码
except Exception:
		当异常发生时,处理异常的代码

例如当使用字符串的index(self, sub, start=None, end=None):方法来查找子串时,如果指定的子串找不到会抛出一个ValueError异常
跟光磊学Python开发-异常机制
跟光磊学Python开发-异常机制

此时可以使用try/except来处理ValueError的异常,如果异常的类型不确定时可以使用Exception替换,例如这里的ValueError可以使用Exception替换,因为异常都直接或者间接继承Exception

"""
使用try/except基本异常处理
@author tony 18601767221@163.com
@version 2021-02-15 15:38:20
@since python3.9.1
"""

s = "hello"

# 使用try来尝试执行可能发生异常的代码
try:
    # ValueError: substring not found
    i = s.index("O")
    print(i)
# 如果发生异常,那么异常信息会被except捕捉到,可以在except后面进行异常处理,如果没有发生异常,程序正常运行,而except就不会执行
except ValueError:
    print("查找的子串不存在")

跟光磊学Python开发-异常机制
跟光磊学Python开发-异常机制
程序运行结果

项目运行过程中可能会发生多个异常,此时可以将多个异常包装成一个元祖。需要注意的是同一时刻只能有一个异常发生,因为只要有一个异常发生,程序不会再往下执行,转而执行except的异常处理的代码。

try:
		可能发生异常的代码
except (异常1,异常2....)as e:
		当异常发生时,处理异常的代码

其中as e表示给异常起别名

"""
多异常处理
@author tony 18601767221@163.com
@version 2021-02-15 16:09:54
@since python3.9.1
"""

try:
    number / 0
except(ZeroDivisionError, NameError) as e:
    print("程序出现了异常", e)

程序运行结果
跟光磊学Python开发-异常机制
跟光磊学Python开发-异常机制

而异常处理的完整语法格式,其中else和finally都是可选的,而finally通常是操作文件、数据库或者网络时关闭资源使用

try:
	可能出现异常的代码
except Exception as e:
	异常处理的代码
else:
	没有出现异常的代码
finally:
	无论是否出现异常,都会执行此语句块

异常处理之 try/except/else/finally:文件不存在异常

"""
异常处理之 try/except/else/finally
@author tony 18601767221@163.com
@version 2021-02-15 16:16:37
@since python3.9.1
"""
try:
    f = None
    f = open("java.txt", "r")
except Exception as e:
    print("要打开的文件不存在")
    print("异常信息是", e)
else:
    content = f.read(1024)
    print("文件内容是", end="	")
    print(content)
finally:
    print("无论程序是否有异常都会执行finally")
    if f != None:
        print("关闭文件资源")
        f.close()

程序运行结果
跟光磊学Python开发-异常机制
跟光磊学Python开发-异常机制

异常处理之 try/except/else/finally:文件存在并关闭文件资源

"""
异常处理之 try/except/else/finally
@author tony 18601767221@163.com
@version 2021-02-15 16:16:37
@since python3.9.1
"""
try:
    f = None
    f = open("python.txt", "r")
except Exception as e:
    print("要打开的文件不存在")
    print("异常信息是", e)
else:
    content = f.read(1024)
    print("文件内容是", end="	")
    print(content)
finally:
    print("无论程序是否有异常都会执行finally")
    if f != None:
        print("关闭文件资源")
        f.close()

程序运行结果
跟光磊学Python开发-异常机制
跟光磊学Python开发-异常机制

异常传递

当代码出现多个层级调用时,其中如果某个环节发生了异常,但是该异常没有处理,默认情况下该异常会向上抛出,如果上层也没有处理,那么会继续再向上层抛出,直到抛到解释器,解释器默认的处理方式就是中断程序,将异常信息打印输出到终端上。

"""
异常传递
@author tony 18601767221@163.com
@version 2021-02-15 15:59:32
@since python3.9.1
"""


def func_a():
    print("execute func_a function")
    func_b()


def func_b():
    print("execute func_b function")
    func_c()


def func_c():
    print("execute func_c function")
    result = 1 / 0
    print(result)


func_a()

跟光磊学Python开发-异常机制
跟光磊学Python开发-异常机制
程序运行结果

此时推荐在func_c()方法处理该异常

"""
异常传递
@author tony 18601767221@163.com
@version 2021-02-15 15:59:32
@since python3.9.1
"""


def func_a():
    print("execute func_a function")
    func_b()


def func_b():
    print("execute func_b function")
    func_c()


def func_c():
    print("execute func_c function")
    try:
        result = 1 / 0
        print(result)
    except ZeroDivisionError:
        print("0不能作为被除数")


func_a()

跟光磊学Python开发-异常机制
跟光磊学Python开发-异常机制
程序运行结果

当然由于异常的传递机制,也可以在func_b()方法或者是func_a()方法来处理异常

"""
异常传递
@author tony 18601767221@163.com
@version 2021-02-15 15:59:32
@since python3.9.1
"""


def func_a():
    print("execute func_a function")
    func_b()


def func_b():
    print("execute func_b function")
    try:
        func_c()
    except ZeroDivisionError:
        print("0不能作为被除数")


def func_c():
    print("execute func_c function")
    result = 1 / 0
    print(result)


func_a()

程序运行结果
跟光磊学Python开发-异常机制
跟光磊学Python开发-异常机制

自定义异常

在业务开发时需要根据对应的业务场景来自定义相关的业务异常。

自定义异常的语法格式

class 异常名Error(Exception):
	
	pass
	

自定义异常

"""
定义一个手机号不是纯数字异常
"""


class PhoneNumberNotDigitError(Exception):
    pass


"""
定义一个手机号长度不合法异常
"""


class PhoneNumberLengthError(Exception):
    def __init__(self, msg):
        self.__msg = msg

    def __str__(self):
        return self.__msg

    pass


系统异常通常是由系统抛出,而自定义异常通常由开发人员手动抛出,其方式是 raise 异常对象,异常对象可以是类对象,也可以是实例对象

def get_phone_number():
    """
    从键盘获取用户输入的手机号,判断是否合法
    :return:
    """
    phone_number = input("请输入一个11位数字的手机号:")
    if phone_number.isdigit() == False:
        # 抛出自定义的异常 异常对象是类对象
        raise PhoneNumberNotDigitError
    elif len(phone_number) != 11:
        # 抛出自定义异常,异常对象是实例对象
        raise PhoneNumberLengthError("异常信息:手机号长度必须是11位")
    return phone_number

通过导入模块调用get_phone_number()函数来处理自定义异常

"""
处理自定义异常
@author tony 18601767221@163.com
@version 2021-02-15 16:49:50
@since python3.9.1
"""
from custom_exception import *

# 处理调用get_phone_number()函数时可能发生的异常
try:
    phone_number = get_phone_number()
except (PhoneNumberLengthError, PhoneNumberNotDigitError) as e:
    print(e)
else:
    print("你输入的手机号是", phone_number)

程序运行结果
跟光磊学Python开发-异常机制
跟光磊学Python开发-异常机制
跟光磊学Python开发-异常机制
跟光磊学Python开发-异常机制
跟光磊学Python开发-异常机制
跟光磊学Python开发-异常机制