一、什么是异常?
异常是程序在运行时期产生的错误,会直接导致程序中断执行。它区别于编译错误(语法错误),是代码逻辑合法但运行时遇到意外情况引发的问题,比如:
- 除零错误
ZeroDivisionError - 文件不存在错误
FileNotFoundError - 类型不匹配错误
TypeError
二、为什么要使用异常处理?
- 避免程序崩溃:让程序在遇到错误时优雅降级,而不是直接终止。
- 精准定位问题:捕获异常后可以输出详细错误信息,快速定位问题。
- 保证资源释放 :通过
finally确保文件、网络连接等资源被正确释放。 - 提升用户体验:可以给用户友好的错误提示,而不是生硬的报错信息。
三、Python 异常处理核心语法
- 基础格式
python
try:
# 可能发生异常的代码块
pass
except 异常类型 as e:
# 异常发生时的处理逻辑
pass
try:包裹可能出现异常的代码。except:捕获指定类型的异常,并执行处理逻辑。as e:将异常对象重命名为e,方便查看错误详情。
else语法
当 try 代码块没有发生异常 时,会执行 else 中的代码。
python
try:
# 可能发生异常的代码
pass
except 异常类型 as e:
# 异常处理逻辑
pass
else:
# 无异常时执行的代码
pass
finally语法
无论 try 代码块是否发生异常,finally 中的代码一定会执行,通常用于释放资源(如关闭文件、数据库连接)。
python
try:
# 可能发生异常的代码
pass
except 异常类型 as e:
# 异常处理逻辑
pass
finally:
# 无论是否异常都会执行的代码
pass
四、实战案例
- 基础异常处理
python
print("start...running...")
# 编译时无语法错误,但运行时会触发除零异常
try:
x = 1 / 0 # 分母为0,触发 ZeroDivisionError
except ZeroDivisionError as e:
print("这里发生了异常问题,请及时处理:", e)
运行结果
python
start...running...
这里发生了异常问题,请及时处理: division by zero
- 捕获文件不存在异常
python
try:
# 尝试打开一个不存在的文件
with open("test_exception.txt", "r", encoding="utf-8") as f:
f.read()
except BaseException as e:
print(e) # 打印异常对象,输出:[Errno 2] No such file or directory: 'test_exception.txt'
说明:
BaseException是所有异常的父类,可以捕获任何类型的异常,适合调试阶段使用。
else与finally组合使用
python
try:
x = int(input("用户输入一个整数:"))
print(1 / x)
except Exception as e:
print(e)
else:
print("异常没有发生,不必理会")
finally:
print("异常无论发生或不发生,都执行,一般用来释放资源")
- 输入合法整数且不为 0 → 执行
try+else+finally。 - 输入非整数或 0 → 执行
except+finally。
finally释放文件资源
python
try:
file = open("io_exception.txt", "w", encoding="utf-8")
file.write("zhangsan")
except Exception as e:
print("写入出现错误,请及时修正")
finally:
file.close() # 确保文件被关闭
print(file.closed) # 验证文件是否关闭,输出:True
print("end....running")
五、多异常处理
1.一次性捕获多个异常
当多个异常的处理逻辑相同时,可以将它们放在同一个 except 块中,用元组包裹异常类型。
python
# #案例:输入一个整数并存储在文件
input_number,mode = (input("请输入一个整数")).split(" ")
try:
with open("test_many_exception",mode,encoding="utf-8") as f:
f.write(str(1/int(input_number)))
except (FileNotFoundError,ZeroDivisionError) as e:
print("异常信息:",e)
核心逻辑
- 将多个异常类型放在一个元组中,一次捕获。
- 所有捕获到的异常共用同一套处理逻辑。
- 适合处理不同异常但错误提示或处理方式一致的场景。
2 .多次捕获异常
当不同异常需要不同处理逻辑时,可以使用多个 except 块,按 "子类异常在前、父类异常在后" 的顺序捕获。
python
try:
with open("test.txt", "r", encoding="utf-8") as f:
f.read()
#多次抓取的情况一般会选择从子类依次进行
except FileNotFoundError as e:
print(f"文件不存在错误:{e}")
except OSError as e:
print(f"系统错误:{e}")
except Exception as e:
print(f"其他异常:{e}")

- 异常捕获会按顺序匹配,一旦匹配成功就不再向下执行。
- 必须将更具体的子类异常(如
FileNotFoundError)放在前面,通用的父类异常(如Exception)放在后面。 - 适合需要为不同异常定制处理逻辑的场景。
六、自定义异常
当内置异常无法满足业务需求时,我们可以通过继承 Exception 类来定义自己的异常,让错误信息更具业务语义。
1.定义自定义异常
python
class AuthenticationException(Exception):
"""自定义认证异常,用于登录场景的错误提示"""
def __init__(self, message):
super().__init__(message)
2 .抛出自定义异常
在业务逻辑中,当触发特定错误时,使用 raise 关键字抛出自定义异常。
python
# 模拟数据库中的用户名和密码
username_database = "zhangsan"
password_database = "111"
def login(username, password):
if username != username_database:
raise AuthenticationException("用户不存在,请先注册")
elif password != password_database:
raise AuthenticationException("密码错误,请重新输入")
else:
print("success....")
- 使用
raise关键字主动抛出异常。 - 异常信息可以直接携带业务场景的具体提示,让错误更易理解。
3 .捕获并处理自定义异常
python
import time
if __name__ == "__main__":
username, password = input("请输入用户名和密码,使用空格隔开:").split(" ")
try:
login(username, password)
except AuthenticationException as e:
# 记录异常日志到文件
with open("log_login.txt", "a+", encoding="utf-8") as f:
log_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
f.write(f"出现时间:{log_time},出现的问题:{e}\n")
print(f"登录失败:{e}")