====== 第十九章:异常处理 ======
===== 本章目标 =====
完成本章学习后,你将能够:
* 理解异常处理机制
* 捕获和处理各种异常
* 创建自定义异常
* 掌握异常处理最佳实践
===== 异常基础 =====
==== 什么是异常 ====
异常是程序执行过程中发生的错误事件,会中断正常程序流程。
# 常见异常
10 / 0 # ZeroDivisionError
int("hello") # ValueError
"hello"[10] # IndexError
{"a": 1}["b"] # KeyError
open("nonexistent") # FileNotFoundError
==== 异常层次结构 ====
BaseException
├── SystemExit
├── KeyboardInterrupt
└── Exception
├── ArithmeticError
│ └── ZeroDivisionError
├── LookupError
│ ├── IndexError
│ └── KeyError
├── TypeError
├── ValueError
├── RuntimeError
└── OSError
└── FileNotFoundError
===== 异常处理 =====
==== try-except ====
try:
result = 10 / 0
except ZeroDivisionError:
print("Cannot divide by zero!")
# 捕获多个异常
try:
# some code
pass
except (TypeError, ValueError) as e:
print(f"Error: {e}")
# 分别处理
try:
value = int(input("Enter a number: "))
result = 100 / value
except ValueError:
print("Invalid input!")
except ZeroDivisionError:
print("Cannot divide by zero!")
==== try-except-else-finally ====
try:
file = open("data.txt", "r")
data = file.read()
except FileNotFoundError:
print("File not found!")
else:
# 没有异常时执行
print(f"File content: {data}")
finally:
# 无论是否异常都执行
print("Cleanup code here")
if 'file' in dir() and not file.closed:
file.close()
===== 自定义异常 =====
class ValidationError(Exception):
"""验证错误基类"""
pass
class InvalidAgeError(ValidationError):
"""年龄无效"""
def __init__(self, age, message="Age must be between 0 and 150"):
self.age = age
self.message = message
super().__init__(self.message)
def __str__(self):
return f"{self.message}, got {self.age}"
class InvalidEmailError(ValidationError):
"""邮箱无效"""
pass
# 使用
def validate_age(age):
if not (0 <= age <= 150):
raise InvalidAgeError(age)
try:
validate_age(200)
except InvalidAgeError as e:
print(e)
===== 异常最佳实践 =====
# 1. 不要捕获所有异常
# 不好
try:
do_something()
except: # 捕获所有,包括SystemExit
pass
# 好
try:
do_something()
except SpecificException as e:
handle_error(e)
# 2. 使用finally释放资源
# 好
with open("file.txt") as f:
process(f)
# 3. 不要忽略异常
# 不好
try:
risky_operation()
except Exception:
pass # 沉默的异常
# 4. 使用raise from保持异常链
try:
int("not a number")
except ValueError as e:
raise CustomError("Failed to parse") from e
===== 本章练习 =====
1. 创建自定义异常类层次结构
2. 实现带重试的装饰器
3. 实现上下文管理器处理异常
4. 编写健壮的输入验证函数
下一章:[[python_course:chapter20|第二十章:模块与包]]