Python异常分类案例如何区分报错

wen python案例 31

本文目录导读:

Python异常分类案例如何区分报错

  1. 异常分类概览
  2. 常见异常区分案例
  3. 实际业务场景异常处理
  4. 自定义异常类(专业做法)
  5. 异常处理最佳实践
  6. 快速诊断指南

我来用实际案例详细说明Python异常的分类和处理方法。

异常分类概览

# 异常体系结构
BaseException
 ├── SystemExit          # 解释器退出
 ├── KeyboardInterrupt   # 用户中断(Ctrl+C)
 ├── GeneratorExit       # 生成器退出
 └── Exception           # 大多数异常基类
      ├── AttributeError      # 属性错误
      ├── IOError             # I/O错误
      ├── ImportError         # 导入错误
      ├── IndexError          # 索引错误
      ├── KeyError            # 键错误
      ├── NameError           # 名称错误
      ├── TypeError           # 类型错误
      ├── ValueError          # 值错误
      ├── ZeroDivisionError   # 除零错误
      └── ...

常见异常区分案例

# 案例1:不同类型异常对比
def exception_comparison():
    # 1. IndexError vs KeyError
    my_list = [1, 2, 3]
    my_dict = {'a': 1, 'b': 2}
    try:
        print(my_list[5])  # IndexError: list index out of range
    except IndexError:
        print("索引越界错误!")
    try:
        print(my_dict['c'])  # KeyError: 'c'
    except KeyError:
        print("键不存在错误!")
    # 2. ValueError vs TypeError
    try:
        int("abc")  # ValueError: invalid literal
    except ValueError:
        print("值转换错误!")
    try:
        "123" + 456  # TypeError: can only concatenate str (not "int") to str
    except TypeError:
        print("类型不匹配错误!")
    # 3. AttributeError vs NameError
    try:
        my_list.appendd(4)  # AttributeError: 'list' object has no attribute 'appendd'
    except AttributeError:
        print("属性不存在错误!")
    try:
        print(undefined_var)  # NameError: name 'undefined_var' is not defined
    except NameError:
        print("变量未定义错误!")
exception_comparison()

实际业务场景异常处理

class DataProcessor:
    """数据处理类,展示各种异常处理"""
    def process_user_data(self, user_data):
        """
        处理用户数据的完整异常处理示例
        """
        try:
            # 1. 检查数据类型
            if not isinstance(user_data, dict):
                raise TypeError(f"期望dict类型,收到{type(user_data)}")
            # 2. 检查必要字段
            required_fields = ['name', 'age', 'email']
            for field in required_fields:
                if field not in user_data:
                    raise KeyError(f"缺少必要字段: {field}")
            # 3. 数据验证
            name = user_data['name']
            if not isinstance(name, str) or len(name) == 0:
                raise ValueError("姓名必须是非空字符串")
            age = user_data['age']
            if not isinstance(age, int) or age < 0 or age > 150:
                raise ValueError(f"年龄不合法: {age}")
            # 4. 处理业务逻辑
            result = self._calculate_score(age)
            # 5. 文件操作可能出错
            with open(f"user_{name}.txt", 'w') as f:
                f.write(str(result))
            return result
        except TypeError as e:
            print(f"类型错误: {e}")
            return None
        except KeyError as e:
            print(f"键错误: {e}")
            return None
        except ValueError as e:
            print(f"值错误: {e}")
            return None
        except IOError as e:
            print(f"文件I/O错误: {e}")
            return None
        except Exception as e:
            print(f"未知错误: {type(e).__name__}: {e}")
            return None
    def _calculate_score(self, age):
        """计算分数(可能抛出除零错误)"""
        try:
            return 100 / (age - 30)  # 当age=30时触发ZeroDivisionError
        except ZeroDivisionError:
            print("警告:年龄恰好为30,使用默认值")
            return 0
# 使用示例
processor = DataProcessor()
# 测试各种异常情况
test_cases = [
    "not a dict",           # TypeError
    {"name": "Alice"},      # KeyError (缺少age和email)
    {"name": "", "age": 25, "email": "a@b.com"},  # ValueError (空姓名)
    {"name": "Bob", "age": 200, "email": "b@c.com"},  # ValueError (年龄过大)
    {"name": "Charlie", "age": 30, "email": "c@d.com"},  # ZeroDivisionError
    {"name": "David", "age": 25, "email": "d@e.com"},  # 正常情况
]
for i, test_data in enumerate(test_cases, 1):
    print(f"\n测试用例 {i}:")
    result = processor.process_user_data(test_data)
    print(f"处理结果: {result}")

自定义异常类(专业做法)

class CustomBusinessError(Exception):
    """自定义业务异常基类"""
    pass
class ValidationError(CustomBusinessError):
    """数据验证错误"""
    def __init__(self, field, message):
        self.field = field
        self.message = message
        super().__init__(f"字段 '{field}' 验证失败: {message}")
class DatabaseError(CustomBusinessError):
    """数据库操作错误"""
    def __init__(self, operation, table, message):
        self.operation = operation
        self.table = table
        self.message = message
        super().__init__(f"数据库操作 '{operation}' 在表 '{table}' 上失败: {message}")
class NetworkError(CustomBusinessError):
    """网络错误"""
    def __init__(self, url, status_code, message):
        self.url = url
        self.status_code = status_code
        self.message = message
        super().__init__(f"访问 {url} 失败,状态码: {status_code}, 错误: {message}")
# 使用自定义异常
def business_operation():
    try:
        # 模拟各种业务错误
        raise ValidationError("email", "邮箱格式不正确")
        # 或
        # raise DatabaseError("INSERT", "users", "重复的主键")
        # 或
        # raise NetworkError("https://api.example.com", 500, "服务器内部错误")
    except ValidationError as e:
        print(f"验证错误: {e}")
        print(f"错误字段: {e.field}")
    except DatabaseError as e:
        print(f"数据库错误: {e}")
        print(f"操作: {e.operation}, 表: {e.table}")
    except NetworkError as e:
        print(f"网络错误: {e}")
        print(f"URL: {e.url}, 状态码: {e.status_code}")
    except CustomBusinessError as e:
        print(f"业务错误: {e}")

异常处理最佳实践

def best_practices():
    """
    异常处理最佳实践示例
    """
    # 1. 具体异常优先,通用异常在后
    try:
        risky_operation()
    except ValueError:
        # 具体异常处理
        pass
    except TypeError:
        # 具体异常处理
        pass
    except Exception:
        # 通用异常处理(兜底)
        pass
    # 2. 尽量捕获特定异常,避免裸except:
    # 不建议:except:  # 捕获所有异常,包括SystemExit
    # 3. 使用else子句(无异常时执行)
    try:
        result = risky_operation()
    except ValueError as e:
        print(f"错误: {e}")
    else:
        print(f"成功: {result}")  # 只有在try块成功时才执行
    # 4. 使用finally子句(始终执行)
    file = None
    try:
        file = open("data.txt", 'r')
        data = file.read()
    except FileNotFoundError:
        print("文件不存在")
    finally:
        if file:
            file.close()  # 确保文件被关闭
    # 5. 异常链(保留原始异常信息)
    try:
        try:
            int("abc")
        except ValueError as e:
            raise RuntimeError("数字转换失败") from e  # 保留原始异常
def risky_operation():
    """模拟有风险的操作"""
    import random
    if random.random() < 0.5:
        raise ValueError("随机错误")
    return "success"

快速诊断指南

def diagnose_exception(exc):
    """
    异常诊断助手函数
    """
    exception_map = {
        IndexError: "列表/元组索引超出范围",
        KeyError: "字典键不存在",
        ValueError: "值不符合预期格式",
        TypeError: "操作或函数应用于不适当类型的对象",
        AttributeError: "对象没有这个属性/方法",
        NameError: "变量未定义",
        ZeroDivisionError: "除零错误",
        FileNotFoundError: "文件不存在",
        ImportError: "模块导入失败",
        SyntaxError: "代码语法错误",
        IndentationError: "缩进错误",
    }
    exc_type = type(exc)
    if exc_type in exception_map:
        return f"{exception_map[exc_type]}: {exc}"
    else:
        return f"未知异常类型 {exc_type.__name__}: {exc}"
# 使用示例
try:
    1/0
except Exception as e:
    print(diagnose_exception(e))  # 除零错误: division by zero
  1. 区分方法:根据错误信息和异常类型名称判断
  2. 处理原则:具体异常优先,通用异常兜底
  3. 最佳实践
    • 只捕获你能处理的异常
    • 使用自定义异常封装业务逻辑
    • 保持异常链完整
    • 合理使用else和finally

好的异常处理不是避免异常,而是优雅地处理异常!

抱歉,评论功能暂时关闭!