跟光磊学Python开发
跟光磊学Python开发-异常机制
异常概述
异常指的是不正常,也就是程序在执行过程中发生了不可预知的问题,导致程序崩溃。
Python中常见的异常类如下,它们都直接或者间接继承自位于builtins.py文件中的Exeption类
- NameError
- TypeError
- ValueError
- AttributeError
- SyntaxError
- IndexError
异常处理
在日常开发中应该尽量避免异常出现,而程序中可能发生异常的情况,可以通过Pyhton提供的异常处理机制来处理异常,从而提高程序的容错性。
异常处理的语法格式为
try:可能发生异常的代码except Exception:当异常发生时,处理异常的代码
例如当使用字符串的index(self, sub, start=None, end=None):方法来查找子串时,如果指定的子串找不到会抛出一个ValueError异常
此时可以使用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('查找的子串不存在')
程序运行结果
项目运行过程中可能会发生多个异常,此时可以将多个异常包装成一个元祖。需要注意的是同一时刻只能有一个异常发生,因为只要有一个异常发生,程序不会再往下执行,转而执行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 / 0except(ZeroDivisionError, NameError) as e: print('程序出现了异常', e)
程序运行结果
而异常处理的完整语法格式,其中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='\t') print(content)finally: print('无论程序是否有异常都会执行finally') if f != None: print('关闭文件资源') f.close()
程序运行结果
异常处理之 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='\t') print(content)finally: print('无论程序是否有异常都会执行finally') if f != None: print('关闭文件资源') f.close()
程序运行结果
异常传递
当代码出现多个层级调用时,其中如果某个环节发生了异常,但是该异常没有处理,默认情况下该异常会向上抛出,如果上层也没有处理,那么会继续再向上层抛出,直到抛到解释器,解释器默认的处理方式就是中断程序,将异常信息打印输出到终端上。
'''异常传递@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()
程序运行结果
此时推荐在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()
程序运行结果
当然由于异常的传递机制,也可以在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()
程序运行结果
自定义异常
在业务开发时需要根据对应的业务场景来自定义相关的业务异常。
自定义异常的语法格式
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)
程序运行结果