Python异常处理
异常处理基础
什么是异常?
异常是程序运行时发生的错误。Python使用异常对象来表示这些错误,并提供了完整的异常处理机制来优雅地处理这些错误。
异常的产生
# 常见的异常情况
print(10 / 0) # ZeroDivisionError
print(undefined_variable) # NameError
print(int('abc')) # ValueError
try-except语句
基本语法
try:
# 可能产生异常的代码
result = 10 / 0
except ZeroDivisionError as e:
# 处理特定类型的异常
print(f"发生除零错误:{e}")
except Exception as e:
# 处理其他类型的异常
print(f"发生其他错误:{e}")
else:
# 没有异常时执行
print("计算成功")
finally:
# 无论是否发生异常都会执行
print("清理工作")
注意事项
不要使用空的except语句捕获所有异常,这可能会掩盖程序中的严重问题。始终指定要捕获的具体异常类型。
常见异常类型
Python内置异常
- SyntaxError:语法错误
- NameError:使用未定义的变量
- TypeError:类型错误
- ValueError:值错误
- IndexError:索引超出范围
- KeyError:字典中不存在的键
- FileNotFoundError:文件不存在
- ImportError:导入模块失败
异常层级
try:
# 尝试打开文件
with open('不存在的文件.txt') as f:
content = f.read()
except FileNotFoundError:
print("文件不存在")
except IOError:
print("IO错误")
except Exception:
print("其他错误")
自定义异常
当内置异常无法满足需求时,我们可以创建自定义异常类:
class InvalidAgeError(Exception):
"""当年龄值无效时抛出的异常"""
def __init__(self, age, message="年龄必须在0-150之间"):
self.age = age
self.message = message
super().__init__(self.message)
def verify_age(age):
if not 0 <= age <= 150:
raise InvalidAgeError(age)
return True
# 使用自定义异常
try:
verify_age(200)
except InvalidAgeError as e:
print(f"错误:{e}")
异常处理最佳实践
推荐做法
- 只捕获预期的特定异常
- 在适当的抽象层次处理异常
- 保持异常处理代码的简洁
- 利用finally子句进行清理
- 提供有意义的错误信息
示例:分层异常处理
def read_user_data(filename):
try:
with open(filename) as f:
return json.load(f)
except FileNotFoundError:
raise UserDataError(f"用户数据文件 {filename} 不存在")
except json.JSONDecodeError:
raise UserDataError("用户数据格式无效")
def process_user(filename):
try:
user_data = read_user_data(filename)
# 处理用户数据
except UserDataError as e:
logger.error(f"处理用户数据失败: {e}")
# 进行适当的错误处理
练习与实践
练习1:安全的数值转换器
创建一个函数,可以安全地将字符串转换为整数,处理各种可能的错误情况。
提示:考虑处理ValueError和TypeError异常,对于无效输入返回默认值。
def safe_int_convert(value, default=None):
"""
安全地将输入值转换为整数
如果转换失败,返回默认值
"""
# 在此编写你的代码
pass
练习2:银行账户管理器
实现一个简单的银行账户类,包含存款和取款方法,使用自定义异常处理各种错误情况。
提示:创建InsufficientFundsError和InvalidAmountError异常类。
class BankAccount:
def __init__(self, balance=0):
self.balance = balance
def deposit(self, amount):
"""存款方法,金额必须为正数"""
# 在此编写你的代码
pass
def withdraw(self, amount):
"""取款方法,金额必须为正数且不能超过余额"""
# 在此编写你的代码
pass