python中级之异常处理
什么是异常
## 异常是程序运行时可能发生的错误或意外情况 ## 本篇博客主要写的是异常相关知识,在 Python 代码的编写过程中经常会出现异常,一般情况下程序员都叫做 出 BUG 了,这个 BUG 就是臭虫的意思,表示程序出臭虫了。当然很多时候我们也戏称“无 BUG,不编程”。
异常的分类
- 内建异常(Built-in Exceptions):由Python内部定义的异常,例如ZeroDivisionError、NameError等。 - 用户自定义异常:由程序员自己定义的异常,用于满足特定的业务需求。
Python 异常捕获是什么
程序异常,就是程序出错了,程序员一般叫做 BUG(八哥),写程序不出错是不可能发生的事情,而程序员要做的事情就是及时的捕获错误,修改错误。
最常见的错误 - 除数为 0
在数学中也存在类似的问题,除数不可以为 0。相同的概念在编程中也是存在的。
num1 = 20 num2 = 0 num3 = num1 / num2 print(num3)
运行代码出现下面的错误:
Traceback (most recent call last): File "D:/gun/2/demo7.py", line 3, in <module> num3 = num1 / num2 ZeroDivisionError: division by zero
错误内容就是末尾的 ZeroDivisionError: division by zero
,当出现错误程序崩溃,终止运行。错误异常中也提示了错误出现的行数 line 3
在第三行,但查看行号排查错误在很多时候无法直接解决问题,因为出错的地方不在行号那一行,修改 BUG 的效率一般会随着你对 Python 学习的深入逐步增强改善。
异常捕获的语法
try … except 语句
刚才的程序出现错误就终止运行了,如何避免程序被强迫终止,出现问题提示出问题,然后继续运行呢?这就是 try … except 语句使用的场景了。
语法格式:
try: 可能会出错的代码 except 异常对象: 处理异常代码
按照上述语法格式修改上文代码。
num1 = 20 num2 = 0 try: num3 = num1 / num2 except ZeroDivisionError: print("除数不可以为 0 ")
此时程序不会报错,当发现除数为 0 会进入异常处理,直接输出除数不能为 0。
try 表示测试代码部分是否存在异常,except 表示捕获异常,前提是出现异常。如果 try 语句中没有任何错误,except 中的代码不会执行。
还有一点需要注意,在 except 后面是异常对象,该异常对象我们设置为 ZeroDivisionError
这是因为已经知道是会出现这个异常,如果在编码过程中不知道会出现哪种异常,依旧会出现错误。
num1 = 20 num2 = "abc" try: num3 = num1 / num2 except ZeroDivisionError: print("除数不可以为 0 ")
上述代码依旧会报错,报错的异常为:
Traceback (most recent call last): File "D:/gun/2/demo7.py", line 4, in <module> num3 = num1 / num2 TypeError: unsupported operand type(s) for /: 'int' and 'str'
如果想在 except 后面支持本异常,需要添加上 TypeError
。
num1 = 20 num2 = "abc" try: num3 = num1 / num2 except (ZeroDivisionError,TypeError): print("除数不可以为 0 ")
也可以分开编写:
num1 = 20 num2 = "abc" try: num3 = num1 / num2 except ZeroDivisionError: print("除数不可以为 0 ") except TypeError: print("除数类型不对")
该种写法在书写的时候需要预先知道会提示哪种异常,如果异常不清楚那可以省略异常对象,直接使用下述代码即可。
num1 = 20 num2 = "abc" try: num3 = num1 / num2 except: print("除数不可以为 0 ")
try … except … else 语句
在 try … except 语句后面可以增加一个 else 语句,该语句表示的含义可以按照如下描述进行理解,当出现异常的时候执行 except 语句中的代码,当无异常执行 else 语句代码。
num1 = 20 num2 = 1 try: num3 = num1 / num2 except ZeroDivisionError: print("除数不可以为 0 ") except TypeError: print("除数类型不对") else: print("无异常,会被执行")
以上代码无错误,那 else 语句就会被执行到。
常见的异常类型
在编写代码的过程中,你需要掌握一些常见的异常类型,熟记它们可以帮助你快速进行错误排查。
- AttributeError 某个对象没有属性
- Exception 通用型异常对象
- FileNotFoundError 找不到文件
- IOError 输入输出异常
- IndexError 索引异常
- KeyError 键异常
- NameError 对象名称异常
- SyntaxError 语法错误
- TypeError 类型错误
- ValueError 值错误
以上错误都属于常见错误,其中重点以 Exception 通用异常对象与 SyntaxError 语法错误为主,它们两个是最常出现的。
很多时候其实直接使用通用异常对象 Exception 就可以了,不需要记住所有的异常类型的。
捕捉多个异常
在上文已经接触过捕捉多个异常的语法格式了,可以在学习一下。
try: 可能出错的代码块 except 异常对象1: 异常处理代码块 except 异常对象2: 异常处理代码块
一个 except 捕获多个异常
Python 也支持使用一个 except 捕获多个异常,具体语法格式如下:
try: 可能出错的代码块 except (异常对象1,异常对象2...): 异常处理代码块
直接抛出异常
捕获到异常之后,可以直接抛出 Python 给内置好的异常信息,例如:
num1 = 20 num2 = 0 try: num3 = num1 / num2 except ZeroDivisionError as e: print(e) except TypeError as e: print(e) else: print("无异常,会被执行")
注意 except 后面异常对象使用 as 关键字起了一个别名叫做 e
,然后直接输出 e
就是 Python 内置好的错误信息了。这里的 e
可以为任意名称,遵循变量命名规则即可。
finally 语句
try … except 语句还可以和 finally 语句配合,形成下述语法格式:
try: 可能出错的代码块 except: 代码出错执行的代码块 else: 代码正常执行的代码块 finally: 无论代码是否有异常出现都会执行的的代码块
finally 语法需要与 try 语句配合使用,无论是否有异常出现都会执行该语句内容,具体代码大家可以自行测试即可。
自定义异常
- 通过创建一个新的异常类,程序可以命名它们自己的异常。
- 异常应该是典型的继承自Exception类,通过直接或间接的方式。
- 以下为与RuntimeError相关的实例
- 实例中创建了一个类,基类为RuntimeError,用于在异常触发时输出更多的信息。
- 在try语句块中
- 用户自定义的异常后执行except块语句
- 变量 e 是用于创建Networkerror类的实例。
- 以下为与RuntimeError相关的实例
class Networkerror(RuntimeError): def __init__(self, arg): self.args = arg # 在你定义以上类后,你可以触发该异常,如下所示: try: raise Networkerror("handsome boy") except Networkerror as e: print(e.args) # ('h', 'a', 'n', 'd', 's', 'o', 'm', 'e', ' ', 'b', 'o', 'y')
Python 异常捕获扩展部分
使用 raise 抛出异常
主动触发异常 --- raise # try: # # print(int('1')) # raise ValueError('字符串的 1 就不允许转换成整型!') # except Exception as e: # error # print(f"这是异常 {e}") # 循环遇到异常也会停止运行 # while True: # raise ValueError()
程序断言 assert
## Python 断言是什么 Python 断言,即 Python assert 语句,简单理解就是简易版的 if 语句,用于判断某个表达式的值,结果为 True,程序运行,否则,程序停止运行,抛出 AssertionError 错误。 语法格式如下所示: ''' assert 表达式 ''' 类比 if 语句,如下所示: if not 表达式: raise AssertionError 在 assert 表达式之后,可以增加一个参数 [, arguments],等价的 if 语句如下所示: if not 表达式: raise AssertionError(arguments) 模拟场景 在游戏里面设置一个未满 18 岁禁止访问的功能。 def overage18(age): assert age >= 18, "对不起未满18岁,无法进行游戏" print("享受欢乐游戏时光") if __name__ == '__main__': overage18(15) 但是这个案例并不是一个完美的案例,因为断言是为了告知开发人员 ,你写的程序发生异常了。如果一个潜在错误在程序编写前就能考虑到,例如程序运行时网络中断,这个场景就不需要使用断言。 断言主要为调试辅助而生,为的是程序自检,并不是为了处理错误,程序 BUG 还是要依赖 try… except 解决。 由于断言是给开发人员看的,所以下述案例的断言是有效的。 def something(): """该函数执行了很多操作""" my_list = [] # 声明了一个空列表 # do something return my_list def func(): """调用 something 函数,基于结果实现某些逻辑""" ret = something() assert len(ret) == 18, "列表元素数量不对" # 完成某些操作 使用断言要注意: 不要用断言验证用户的输入,这是因为 python 通过命令行运行时,如果增加 -O 标识,断言就被全局禁止了,你的所有验证就都丢失了。 常用断言函数 assertEqual(a,b,msg=msg):判断两个值是否相等; assertNotEqual(a,b,msg=msg):上一函数的反义; self.assertTrue(a,msg=none):判断变量是否为 True; assertFalse(a,msg=none):同上反义; assertIsNone(obj=‘’):判断 obj 是否为空; assertIsNotNone(obj=‘’):同上反义; 还有其它函数,你可以任意检索资料,极容易掌握相关用法。 扩展知识 Python 断言的适用场景 进行防御性的编程 我们在使用断言的时候,应该捕捉不应该发生的非法情况。这里要注意非法情况与异常错误之间的区别, 后者是必然存在的并且是一定要作出处理的。而断言后的条件不一定发生。 对假定条件做验证 断言是对程序员的假定做验证,因此这些假定的异常不一定会触发。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏