Python异常处理
1 异常基础
1.1 常见异常类型
SyntaxError
: 语法错误
NameError
: 未定义的变量
TypeError
: 类型错误
ValueError
: 值错误
IndexError
: 索引错误
KeyError
: 字典键错误
FileNotFoundError
: 文件未找到
ZeroDivisionError
: 除零错误
AttributeError
: 属性错误
1.2 基本异常处理
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("程序执行结束")
2 异常处理进阶
2.1 多个异常处理
def process_data(data):
try:
if not isinstance(data, list):
raise TypeError("输入必须是列表类型")
result = []
for item in data:
number = float(item)
if number < 0:
raise ValueError("不能处理负数")
result.append(number * 2)
return result
except (TypeError, ValueError) as e:
print(f"数据处理错误:{e}")
return None
except Exception as e:
print(f"未知错误:{e}")
return None
2.2 自定义异常
class CustomError(Exception):
"""自定义异常类"""
def __init__(self, message):
self.message = message
super().__init__(self.message)
class AgeError(CustomError):
"""年龄相关的异常"""
pass
def verify_age(age):
if not isinstance(age, int):
raise TypeError("年龄必须是整数")
if age < 0:
raise AgeError("年龄不能为负数")
if age > 150:
raise AgeError("年龄不能超过150岁")
3 上下文管理器
3.1 with语句
# 文件操作
def read_file(filename):
try:
with open(filename, 'r', encoding='utf-8') as file:
content = file.read()
return content
except FileNotFoundError:
print(f"文件 {filename} 不存在")
except IOError as e:
print(f"读取文件时发生错误:{e}")
3.2 自定义上下文管理器
class DatabaseConnection:
def __init__(self, host, port):
self.host = host
self.port = port
self.connection = None
def __enter__(self):
print(f"连接到数据库 {self.host}:{self.port}")
self.connection = "数据库连接对象"
return self.connection
def __exit__(self, exc_type, exc_val, exc_tb):
print("关闭数据库连接")
if exc_type is not None:
print(f"发生异常:{exc_type.__name__}: {exc_val}")
return False # 返回False则异常会继续传播
4 最佳实践
4.1 异常处理原则
def divide_numbers(a, b):
try:
# 只在可能发生异常的代码周围使用try-except
return a / b
except ZeroDivisionError:
# 只捕获预期的特定异常
print("除数不能为零")
return None
4.2 日志记录
import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
def process_user_data(user_id):
try:
# 处理用户数据
user = get_user(user_id)
result = analyze_data(user)
return result
except ValueError as e:
logging.error(f"处理用户 {user_id} 数据时发生错误: {e}")
raise
except Exception as e:
logging.critical(f"发生未知错误: {e}")
raise
4.3 清理资源
class Resource:
def __init__(self, name):
self.name = name
print(f"资源 {name} 已创建")
def cleanup(self):
print(f"清理资源 {self.name}")
def use_resource():
resource = None
try:
resource = Resource("测试资源")
# 使用资源
raise ValueError("测试异常")
except Exception as e:
print(f"发生错误:{e}")
finally:
# 确保资源被清理
if resource:
resource.cleanup()
5 实践应用
5.1 文件处理示例
def safe_read_json(filename):
import json
try:
with open(filename, 'r', encoding='utf-8') as f:
data = json.load(f)
return data
except FileNotFoundError:
print(f"文件 {filename} 不存在")
except json.JSONDecodeError as e:
print(f"JSON解析错误:{e}")
except Exception as e:
print(f"未知错误:{e}")
return None
5.2 网络请求示例
import requests
def fetch_data(url):
try:
response = requests.get(url, timeout=5)
response.raise_for_status() # 检查HTTP错误
return response.json()
except requests.Timeout:
print("请求超时")
except requests.HTTPError as e:
print(f"HTTP错误:{e}")
except requests.RequestException as e:
print(f"请求错误:{e}")
except ValueError: # JSON解析错误
print("返回数据格式错误")
return None
练习题
- 实现一个安全的除法计算器,处理各种可能的输入错误
- 编写一个文件复制函数,包含完整的异常处理
- 实现一个简单的数据库连接池,使用上下文管理器管理连接
小结
- 理解Python异常机制
- 掌握异常处理的基本语法
- 能够创建和使用自定义异常
- 理解上下文管理器的使用
- 掌握异常处理的最佳实践
- 能够在实际应用中正确处理异常