欢迎光临
我们一直在努力

Python异常处理

Python 异常处理全攻略:try/except/else/finally、自定义异常、with 语句一文搞定

📌 程序运行时难免出错,Python 的异常处理机制让你优雅地应对错误,而不是让程序直接崩溃。本文系统梳理 Python 异常处理的核心知识点,从基础的 try/except 到自定义异常,配合丰富代码示例,适合初学者收藏学习。


📑 目录

  • 一、异常是什么?
  • 二、try/except 基础捕获
  • 三、捕获指定类型异常
  • 四、else:没有异常时执行
  • 五、finally:无论如何都执行
  • 六、向上抛出异常
  • 七、with 语句:优雅管理资源
  • 八、自定义异常类
  • 九、综合实战
  • 十、总结

一、异常是什么?

Python 中语法正确的代码,在运行时也可能发生错误,这种运行期检测到的错误称为异常(Exception)。

🎯 异常处理的目的不是"规避错误",而是当错误发生时提供解决方案,让程序继续执行而不是直接崩溃。

常见异常类型:

异常类型说明示例
ZeroDivisionError 除以零 10 / 0
NameError 变量未定义 print(未定义变量)
TypeError 类型错误 1 + 'str'
ValueError 值错误 int('abc')
IndexError 索引越界 [][0]
KeyError 字典键不存在 {}['key']
FileNotFoundError 文件不存在 open('不存在.txt')

二、try/except 基础捕获

使用 try/except 语句捕获异常并处理:

try:
result = 3 / 0 # 可能发生异常的代码
print('没有发生异常') # 这行不会执行
except:
print('发生了异常') # 捕获到异常后执行

print('End') # 程序继续运行

执行逻辑:

没有发生异常 → 忽略 except 中的代码,继续向下执行
发生异常 → 忽略 try 中剩余代码,执行 except 中的代码


三、捕获指定类型异常

实际开发中,我们通常需要针对不同异常做不同处理,并获取异常描述信息:

try:
# result = 3 / 0 # ZeroDivisionError
# print(1 + 'str') # TypeError
# print(res_) # NameError
pass
except ZeroDivisionError as e:
print(f'除零错误: {e}')
except NameError as e:
print(f'名称错误: {e}')
except TypeError as e:
print(f'类型错误: {e}')
except RuntimeError as e:
print(f'运行时错误: {e}')
except:
print('Unexpected error') # 兜底:捕获所有未匹配的异常

print('End')

异常匹配规则:

1. 没有异常 → 忽略所有 except,继续执行
2. 发生异常 → 根据异常类型匹配对应的 except 并执行
3. 异常类型无法匹配任何 except → 异常向外传递(程序崩溃)

💡 多个异常可以合并处理:

except (TypeError, ValueError) as e:
print(e)


四、else:没有异常时执行

else 块在 try 中没有发生异常时执行:

try:
result = 10 / 1
except ZeroDivisionError as e:
print(e)
else:
print(result) # 10.0(没有异常时执行)

为什么要用 else 而不是把代码放在 try 里?

虽然执行效果一样,但放在 else 中更利于代码维护和理解——try 中只放可能出错的代码,else 中放正常逻辑。


五、finally:无论如何都执行

finally 块无论是否发生异常都会执行,常用于资源释放、关闭连接等清理操作:

try:
res = 10 / 0
except NameError as e:
print(e)
except ZeroDivisionError as e:
print(e)
else:
print(res)
finally:
print('Finally 正常结束') # 无论如何都会执行

print('End')

finally vs try/except 外部代码

场景放在 finally 中放在 try/except 外
try 正常结束 ✅ 执行 ✅ 执行
try 异常且 except 捕获 ✅ 执行 ✅ 执行
try 异常但 except 未捕获 ✅ 执行 ❌ 不执行(异常向外传递)

🎯 结论: finally 比外部代码更可靠。当 try 中发生未被捕获的异常时,finally 依然会执行,而外部代码不会。


六、向上抛出异常

6.1 raise:主动抛出异常

当你需要在代码中主动触发异常时,使用 raise:

def add(a, b):
if isinstance(a, int) and isinstance(b, int):
return a + b
else:
raise TypeError('参数必须是整数类型')

try:
print(add(1, '2'))
except TypeError as e:
print(e) # 参数必须是整数类型

6.2 assert:断言

assert 用于调试程序,当表达式为 False 时触发异常:

def add(a, b):
assert isinstance(a, int) and isinstance(b, int), '参数错误'
return a + b

try:
print(add(1.0, 2))
except AssertionError as e:
print(e) # 参数错误

关键字语法用途
raise raise 异常类型("描述") 主动抛出异常,用于业务逻辑
assert assert 表达式, "描述" 调试断言,条件为 False 时触发

七、with 语句:优雅管理资源

with 语句可以自动管理资源的获取与释放,等效于 try/finally,但更简洁。

工作原理

with 要求对象实现 __enter__ 和 __exit__ 方法:

1. 进入 with → 调用 __enter__() 获取资源
2. 执行代码块
3. 离开 with → 自动调用 __exit__() 释放资源(无论是否异常)

文件操作对比

不用 with(繁琐):

try:
file = open('test.txt', 'w')
try:
file.write('hello world')
finally:
file.close()
finally:
print('文件是否关闭', file.closed)

用 with(推荐):

try:
with open('test.txt', 'w') as f:
f.write('hello world')
finally:
print('文件是否关闭', f.closed) # True(自动关闭)

💡 with 等效于 try/finally,无论代码是否正常运行,都会执行 __exit__ 释放资源。


八、自定义异常类

Python 允许你继承 Exception 类来创建自定义异常,使异常语义更清晰:

class InvalidAgeError(Exception):
"""无效年龄异常"""
def __init__(self, age):
self.age = age

def __str__(self):
return f"无效年龄: {self.age},年龄不能为负数"

class UnrealisticAgeError(Exception):
"""不现实的年龄异常"""
def __init__(self, age):
self.age = age

def __str__(self):
return f"不现实的年龄: {self.age},年龄不能超过120"

def check_age(age):
if age < 0:
raise InvalidAgeError(age)
elif age > 120:
raise UnrealisticAgeError(age)
return age

try:
age = check_age(int(input('请输入年龄: ')))
print(f'年龄: {age}')
except UnrealisticAgeError as e:
print(e)
except InvalidAgeError as e:
print(e)

自定义异常的优势:

  • 语义更明确:InvalidAgeError 比 ValueError 更直观
  • 可以携带自定义属性(如 self.age)
  • 便于分层处理不同业务异常

九、综合实战

场景1:安全的类型转换 + 文件写入

将用户输入转换为整数,失败时把错误信息写入日志文件:

P_s = "123abc"

try:
P_i = int(P_s)
except ValueError as e:
with open('test.txt', 'w+') as f:
f.write(str(e)) # 写入错误信息:invalid literal for int()…
else:
print(P_i)
finally:
print('文件是否关闭', f.closed) # True

场景2:自定义异常验证用户输入

class InvalidAgeError(Exception):
def __init__(self, age):
self.age = age
def __str__(self):
return f"无效年龄: {self.age},年龄不能为负数"

class UnrealisticAgeError(Exception):
def __init__(self, age):
self.age = age
def __str__(self):
return f"不现实的年龄: {self.age},年龄不能超过120"

def check_age(age):
if age < 0:
raise InvalidAgeError(age)
elif age > 120:
raise UnrealisticAgeError(age)
return age

try:
age = check_age(200)
print(f'年龄: {age}')
except UnrealisticAgeError as e:
print(e) # 不现实的年龄: 200,年龄不能超过120
except InvalidAgeError as e:
print(e)


十、总结

关键字作用执行条件
try 包裹可能出错的代码
except 捕获并处理异常 发生匹配的异常时
else 正常逻辑 try 中没有异常时
finally 清理工作 无论如何都执行
raise 主动抛出异常 业务需要时
assert 调试断言 表达式为 False 时
with 自动资源管理 等效于 try/finally

异常处理最佳实践:

  • 不要用裸 except:尽量捕获具体异常类型,避免吞掉所有错误
  • try 中只放可能出错的代码:正常逻辑放 else 中
  • 资源释放放 finally:或直接用 with 语句
  • 自定义异常继承 Exception:语义更清晰,便于分层处理
  • assert 只用于调试:不要用它做业务校验
  • 🎯 一句话总结: try 管出错,except 管处理,else 管正常,finally 管收尾。掌握这四个关键字,Python 异常处理就通关了。


    如果这篇文章对你有帮助,欢迎点赞 👍 收藏 ⭐ 评论 💬 支持一下!

    赞(0)
    未经允许不得转载:171主机测评 » Python异常处理
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址