我们来详细讲解 Python 中用于异常处理的关键字。
异常处理是编程中超级重大的概念,它允许程序在遇到错误时优雅地处理问题,而不是直接崩溃。Python 提供了一套完整的关键字来处理异常
一、异常处理核心关键字
1.try- 尝试执行
- 功能:用于包裹可能会抛出异常的代码块。
- 位置:必须是异常处理块的开始。
- 规则:try 块必须至少有一个 except 或 finally 块配合使用。
2.except- 捕获异常
- 功能:用于捕获和处理在 try 块中发生的特定异常。
- 变体:
- except ExceptionType: 捕获特定类型的异常
- except ExceptionType as e: 捕获异常并获取异常对象
- except: 捕获所有类型的异常(不推荐常规使用)
- 多个 except 块:处理不同类型的异常
3.else- 无异常时执行
- 功能:当 try 块中的代码没有抛出任何异常时执行。
- 位置:必须在所有 except 块之后,finally 块之前。
4.finally- 最终执行
- 功能:无论是否发生异常都会执行的代码块。
- 用途:一般用于清理资源,如关闭文件、数据库连接等。
二、主动引发异常关键字
5.raise- 抛出异常
- 功能:主动抛出一个异常。
- 用途:在检测到错误条件时主动引发异常,或者在处理异常后重新抛出。
6.assert- 断言
- 功能:用于调试,检查条件是否为真。如果条件为假,则抛出 AssertionError 异常。
- 特点:可以用 -O(优化)参数运行 Python 来禁用所有断言。
三、完整语法结构
try:
# 可能会抛出异常的代码
...
except ExceptionType1 as e:
# 处理 ExceptionType1 类型的异常
...
except ExceptionType2:
# 处理 ExceptionType2 类型的异常
...
except:
# 处理所有其他异常(谨慎使用)
...
else:
# 如果没有异常发生,执行这里的代码
...
finally:
# 无论是否发生异常,都会执行的代码
...
四、详细示例
示例 1:基本的异常处理
try:
num = int(input("请输入一个数字: "))
result = 10 / num
print(f"结果是: {result}")
except ValueError:
print("错误:请输入有效的数字!")
except ZeroDivisionError:
print("错误:不能除以零!")
except Exception as e:
print(f"发生了未知错误: {e}")
else:
print("计算成功完成!")
finally:
print("程序执行结束。")
# 可能的输出:
# 请输入一个数字: abc
# 错误:请输入有效的数字!
# 程序执行结束。
示例 2:使用 else 和 finally
def read_file(filename):
try:
file = open(filename, 'r')
content = file.read()
except FileNotFoundError:
print(f"文件 {filename} 不存在")
return None
except PermissionError:
print("没有读取文件的权限")
return None
else:
print("文件读取成功")
return content
finally:
# 确保文件总是被关闭
if 'file' in locals() and not file.closed:
file.close()
print("文件已关闭")
content = read_file("example.txt")
示例 3:主动抛出异常 (raise)
def calculate_age(birth_year):
if birth_year < 1900 or birth_year > 2023:
raise ValueError("出生年份必须在1900-2023之间")
return 2023 - birth_year
try:
age = calculate_age(1800)
print(f"年龄: {age}")
except ValueError as e:
print(f"输入错误: {e}")
# 重新抛出异常
try:
risky_operation()
except Exception as e:
print(f"记录错误: {e}")
raise # 重新抛出一样的异常
示例 4:自定义异常
class InsufficientFundsError(Exception):
"""自定义异常:余额不足"""
def __init__(self, balance, amount):
self.balance = balance
self.amount = amount
super().__init__(f"余额不足!当前余额: {balance}, 需要: {amount}")
def withdraw(balance, amount):
if amount > balance:
raise InsufficientFundsError(balance, amount)
return balance - amount
try:
new_balance = withdraw(100, 150)
except InsufficientFundsError as e:
print(e) # 输出: 余额不足!当前余额: 100, 需要: 150
示例 5:断言 (assert)
def calculate_average(numbers):
"""计算数字列表的平均值"""
assert len(numbers) > 0, "列表不能为空"
assert all(isinstance(num, (int, float)) for num in numbers), "所有元素必须是数字"
return sum(numbers) / len(numbers)
# 正常情况
print(calculate_average([1, 2, 3, 4, 5])) # 输出: 3.0
# 会触发断言错误
try:
calculate_average([])
except AssertionError as e:
print(f"断言错误: {e}") # 输出: 断言错误: 列表不能为空
示例 6:多个异常处理
def process_data(data):
try:
# 尝试多种可能失败的操作
value = data['key'] # 可能KeyError
number = int(value) # 可能ValueError
result = 100 / number # 可能ZeroDivisionError
except KeyError:
print("错误:字典中不存在该键")
except ValueError:
print("错误:无法转换为数字")
except ZeroDivisionError:
print("错误:不能除以零")
else:
print(f"处理结果: {result}")
return result
finally:
print("数据处理流程结束")
# 测试不同的错误情况
process_data({'key': '10'}) # 正常
process_data({'wrong': '10'}) # KeyError
process_data({'key': 'abc'}) # ValueError
process_data({'key': '0'}) # ZeroDivisionError
五、常见的异常类型
|
异常类型 |
描述 |
|
Exception |
所有内置异常的基类 |
|
ValueError |
值错误,如 int('abc') |
|
TypeError |
类型错误,如 'a' + 1 |
|
IndexError |
索引错误,如 list[10](列表只有3个元素) |
|
KeyError |
键错误,如 dict['nonexistent'] |
|
FileNotFoundError |
文件未找到错误 |
|
ZeroDivisionError |
除以零错误 |
|
AttributeError |
属性错误,如 None.some_method() |
总结表
|
关键字 |
功能描述 |
示例 |
|
try |
尝试执行可能出错的代码 |
try: |
|
except |
捕获和处理异常 |
except ValueError: |
|
else |
无异常时执行的代码 |
else: |
|
finally |
无论是否异常都执行的代码 |
finally: |
|
raise |
主动抛出异常 |
raise ValueError(“错误”) |
|
assert |
断言检查,用于调试 |
assert x > 0, “x必须大于0” |
最佳实践提议:
- 具体异常:尽量捕获具体的异常类型,而不是使用空的 except:。
- 资源清理:使用 finally 或上下文管理器(with 语句)来确保资源被正确释放。
- 异常信息:在抛出异常时提供有意义的错误信息。
- 不要过度使用:异常处理应该用于真正的异常情况,而不是普通的控制流。
掌握这些异常处理关键字可以让你的程序更加健壮和可靠。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
相关文章
暂无评论...





