跳转至

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

练习题

  1. 实现一个安全的除法计算器,处理各种可能的输入错误
  2. 编写一个文件复制函数,包含完整的异常处理
  3. 实现一个简单的数据库连接池,使用上下文管理器管理连接

小结

  • 理解Python异常机制
  • 掌握异常处理的基本语法
  • 能够创建和使用自定义异常
  • 理解上下文管理器的使用
  • 掌握异常处理的最佳实践
  • 能够在实际应用中正确处理异常