本文目录导读:
在Python中,报错捕获主要通过try-except语句实现,以下是各种常见案例:
基础用法
try:
# 可能引发异常的代码
result = 10 / 0
except ZeroDivisionError:
print("除数不能为0")
捕获多种异常
try:
num = int(input("请输入数字: "))
result = 10 / num
except ValueError:
print("输入的不是有效数字")
except ZeroDivisionError:
print("除数不能为0")
except Exception as e:
print(f"发生未知错误: {e}")
获取异常信息
try:
data = [1, 2, 3]
print(data[5])
except IndexError as e:
print(f"索引错误: {e}")
print(f"错误类型: {type(e).__name__}")
try-except-else-finally 完整结构
def read_file(filename):
try:
file = open(filename, 'r')
content = file.read()
except FileNotFoundError:
print(f"文件 {filename} 不存在")
return
except PermissionError:
print(f"没有权限读取文件 {filename}")
return
else:
# 没有异常时执行
print(f"成功读取文件,共 {len(content)} 个字符")
return content
finally:
# 无论是否异常都会执行
print("文件操作结束")
try:
file.close()
except:
pass
自定义异常类
class AgeError(Exception):
"""年龄验证异常"""
def __init__(self, age, message="年龄不合法"):
self.age = age
self.message = message
super().__init__(self.message)
class User:
def set_age(self, age):
if age < 0:
raise AgeError(age, "年龄不能为负数")
elif age > 150:
raise AgeError(age, "年龄超出合理范围")
self._age = age
# 使用自定义异常
try:
user = User()
user.set_age(200)
except AgeError as e:
print(f"错误: {e.message}, 输入年龄: {e.age}")
常见实际应用场景
文件操作
try:
with open('config.json', 'r') as f:
config = json.load(f)
except FileNotFoundError:
config = {} # 使用默认配置
print("使用默认配置")
except json.JSONDecodeError:
print("配置文件格式错误")
config = {}
网络请求
import requests
import time
def fetch_data(url, retries=3):
for i in range(retries):
try:
response = requests.get(url, timeout=5)
response.raise_for_status() # 检查HTTP状态码
return response.json()
except requests.Timeout:
print(f"请求超时,第{i+1}次重试")
if i == retries - 1:
raise
except requests.ConnectionError:
print("网络连接错误")
break
except requests.RequestException as e:
print(f"请求失败: {e}")
break
数据库操作
import sqlite3
def save_user(name, email):
conn = None
try:
conn = sqlite3.connect('users.db')
cursor = conn.cursor()
cursor.execute(
"INSERT INTO users (name, email) VALUES (?, ?)",
(name, email)
)
conn.commit()
except sqlite3.IntegrityError:
print(f"用户 {email} 已存在")
return False
except sqlite3.OperationalError as e:
print(f"数据库操作错误: {e}")
return False
finally:
if conn:
conn.close()
return True
异常链和重新抛出
def process_data(data):
try:
return data.upper()
except AttributeError as e:
# 异常链 - 保留原始异常信息
raise ValueError("数据必须是字符串") from e
def main():
try:
result = process_data(123)
except ValueError as e:
print(f"处理失败: {e}")
print(f"原始错误: {e.__cause__}") # 查看原始异常
断言和预防性检查
def divide(a, b):
# 预防性检查
if b == 0:
raise ValueError("除数不能为0")
# 类型检查
if not isinstance(a, (int, float)):
raise TypeError("被除数必须是数字")
return a / b
try:
print(divide(10, 'a'))
except (ValueError, TypeError) as e:
print(f"参数错误: {e}")
最佳实践建议
- 具体优于通用:尽量捕获具体异常,避免使用
except:(捕获所有异常) - 最小化try块:只包裹可能出错的代码
- 不要忽略异常:至少记录日志
- 使用with语句:自动管理资源
- 考虑异常链:重新抛出时保留上下文
import logging
# 配置日志
logging.basicConfig(level=logging.ERROR)
def safe_operation():
try:
# 只包裹可能出错的代码
risky_code()
except SpecificError as e:
# 处理已知错误
logging.error(f"特定错误: {e}")
return fallback_value
except Exception as e:
# 记录未知错误
logging.exception("未知错误")
raise # 重新抛出
这些案例涵盖了Python异常处理的主要场景,根据实际需求选择合适的方式进行错误处理。
标签: 错误处理