Python案例如何捕获异常

wen python案例 45

本文目录导读:

Python案例如何捕获异常

  1. 基础异常捕获结构
  2. 实际应用案例
  3. 高级异常处理技巧
  4. 实际项目中的最佳实践
  5. 异常捕获的注意事项

我来详细讲解Python中捕获异常的多种方法和实践案例。

基础异常捕获结构

try-except 基础用法

# 基础捕获
try:
    result = 10 / 0
except ZeroDivisionError:
    print("除数不能为零!")
# 捕获多个异常
try:
    num = int(input("请输入数字:"))
    result = 10 / num
except ValueError:
    print("请输入有效的数字!")
except ZeroDivisionError:
    print("除数不能为零!")
# 捕获所有异常(不推荐,应尽量精确)
try:
    # 一些操作
    pass
except Exception as e:
    print(f"发生错误:{e}")

实际应用案例

案例1:文件操作异常处理

def read_file(filename):
    """安全读取文件"""
    try:
        with open(filename, 'r', encoding='utf-8') as file:
            content = file.read()
            return content
    except FileNotFoundError:
        print(f"错误:文件 '{filename}' 不存在")
        return None
    except PermissionError:
        print(f"错误:没有权限读取文件 '{filename}'")
        return None
    except Exception as e:
        print(f"读取文件时发生未知错误:{e}")
        return None
# 使用示例
content = read_file("data.txt")
if content:
    print("文件内容:", content[:100])

案例2:网络请求异常处理

import requests
from requests.exceptions import RequestException, Timeout, ConnectionError
def fetch_data(url, timeout=5):
    """安全获取网络数据"""
    try:
        response = requests.get(url, timeout=timeout)
        response.raise_for_status()  # 检查HTTP状态码
        return response.json()
    except Timeout:
        print(f"错误:请求超时({timeout}秒)")
        return None
    except ConnectionError:
        print(f"错误:无法连接到 {url}")
        return None
    except RequestException as e:
        print(f"网络请求错误:{e}")
        return None
    except ValueError as e:
        print(f"JSON解析错误:{e}")
        return None
# 使用示例
data = fetch_data("https://api.example.com/data")
if data:
    print("获取的数据:", data)

案例3:数据库操作异常处理

import sqlite3
from sqlite3 import Error as SQLError
class DatabaseManager:
    def __init__(self, db_path):
        self.db_path = db_path
        self.connection = None
    def connect(self):
        """安全连接数据库"""
        try:
            self.connection = sqlite3.connect(self.db_path)
            print("数据库连接成功")
            return True
        except SQLError as e:
            print(f"数据库连接失败:{e}")
            return False
    def execute_query(self, query, params=None):
        """安全执行SQL查询"""
        try:
            cursor = self.connection.cursor()
            if params:
                cursor.execute(query, params)
            else:
                cursor.execute(query)
            self.connection.commit()
            return cursor.fetchall()
        except SQLError as e:
            print(f"SQL执行错误:{e}")
            self.connection.rollback()
            return None
        except AttributeError as e:
            print(f"数据库未连接:{e}")
            return None
    def close(self):
        """安全关闭连接"""
        try:
            if self.connection:
                self.connection.close()
                print("数据库连接已关闭")
        except SQLError as e:
            print(f"关闭连接时出错:{e}")
# 使用示例
db = DatabaseManager("test.db")
if db.connect():
    result = db.execute_query("SELECT * FROM users")
    if result:
        for row in result:
            print(row)
    db.close()

高级异常处理技巧

完整的异常处理结构

def advanced_error_handling():
    """演示完整的异常处理结构"""
    try:
        # 尝试执行的代码
        print("正在执行操作...")
        x = int(input("请输入数字:"))
        result = 100 / x
        print(f"结果:{result}")
    except ValueError:
        # 处理特定异常
        print("请输入有效数字!")
    except ZeroDivisionError:
        # 处理除零异常
        print("除数不能为零!")
    except Exception as e:
        # 处理其他所有异常
        print(f"未知错误:{type(e).__name__}: {e}")
    else:
        # 没有异常时执行
        print("操作成功完成!")
    finally:
        # 无论是否有异常都会执行
        print("清理工作:关闭资源等")
# 运行示例
advanced_error_handling()

自定义异常类

class CustomError(Exception):
    """自定义异常基类"""
    def __init__(self, message, code=None):
        self.message = message
        self.code = code
        super().__init__(self.message)
    def __str__(self):
        if self.code:
            return f"[{self.code}] {self.message}"
        return self.message
class ValidationError(CustomError):
    """数据验证错误"""
    pass
class BusinessError(CustomError):
    """业务逻辑错误"""
    pass
# 使用自定义异常
def validate_age(age):
    """验证年龄"""
    if not isinstance(age, int):
        raise ValidationError("年龄必须是整数", code=1001)
    if age < 0 or age > 150:
        raise ValidationError(f"年龄 {age} 超出有效范围", code=1002)
    return True
def process_user_data(age):
    """处理用户数据"""
    try:
        validate_age(age)
        print(f"年龄 {age} 验证通过")
    except ValidationError as e:
        print(f"验证失败:{e}")
        # 根据错误码处理
        if e.code == 1001:
            print("建议:请输入整数")
        elif e.code == 1002:
            print("建议:请输入0-150之间的年龄")
    except Exception as e:
        print(f"处理错误:{e}")
# 测试
process_user_data("25")   # 类型错误
process_user_data(200)    # 范围错误
process_user_data(25)     # 正确

实际项目中的最佳实践

案例:完整的API调用封装

import time
import logging
from functools import wraps
# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def retry_on_failure(max_retries=3, delay=1):
    """重试装饰器"""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            last_exception = None
            for attempt in range(max_retries):
                try:
                    return func(*args, **kwargs)
                except (ConnectionError, TimeoutError) as e:
                    last_exception = e
                    logger.warning(f"尝试 {attempt + 1}/{max_retries} 失败:{e}")
                    if attempt < max_retries - 1:
                        time.sleep(delay * (attempt + 1))  # 指数退避
            logger.error(f"所有重试都失败")
            raise last_exception
        return wrapper
    return decorator
class SafeAPIClient:
    """安全的API客户端"""
    def __init__(self, base_url, api_key=None):
        self.base_url = base_url
        self.api_key = api_key
        self.session = requests.Session()
        if api_key:
            self.session.headers.update({"Authorization": f"Bearer {api_key}"})
    @retry_on_failure(max_retries=3)
    def get_user_data(self, user_id):
        """获取用户数据(带重试机制)"""
        try:
            url = f"{self.base_url}/users/{user_id}"
            response = self.session.get(url, timeout=10)
            response.raise_for_status()
            return response.json()
        except requests.exceptions.HTTPError as e:
            if response.status_code == 404:
                logger.error(f"用户 {user_id} 不存在")
                return None
            elif response.status_code == 401:
                logger.error("认证失败")
                raise PermissionError("API密钥无效")
            else:
                raise
        except requests.exceptions.ConnectionError:
            logger.error("网络连接失败")
            raise ConnectionError("无法连接到API服务器")
        except requests.exceptions.Timeout:
            logger.error("请求超时")
            raise TimeoutError("API请求超时")
        except Exception as e:
            logger.exception(f"获取用户数据时发生未知错误")
            raise
    def close(self):
        """安全关闭会话"""
        try:
            self.session.close()
        except Exception as e:
            logger.error(f"关闭会话时出错:{e}")
# 使用示例
client = SafeAPIClient("https://api.example.com", api_key="your-api-key")
try:
    user_data = client.get_user_data(12345)
    if user_data:
        print(f"用户数据:{user_data}")
except (ConnectionError, TimeoutError) as e:
    print(f"网络错误:{e}")
except PermissionError as e:
    print(f"权限错误:{e}")
finally:
    client.close()

异常捕获的注意事项

常见陷阱和最佳实践

# ❌ 不好的做法:空except
try:
    risky_operation()
except:
    pass  # 错误被忽略
# ✅ 好的做法:指定异常类型
try:
    risky_operation()
except (ValueError, TypeError) as e:
    logger.error(f"输入验证错误:{e}")
# ❌ 不好的做法:同时捕获异常又不处理
try:
    result = calculate()
except Exception:
    # 没有任何处理
    pass
# ✅ 好的做法:始终进行适当的错误处理
try:
    result = calculate()
except Exception as e:
    logger.error(f"计算失败:{e}")
    result = 0  # 设置默认值
    raise  # 或者重新抛出异常
# ❌ 不好的做法:过于宽泛的异常处理
try:
    process_data()
except Exception:
    print("出错了")  # 丢失错误信息
# ✅ 好的做法:记录详细信息
try:
    process_data()
except Exception as e:
    logger.exception("处理数据时出错")  # 记录完整堆栈跟踪
    raise CustomError("数据处理失败", original_error=e)
  1. 精确捕获:尽量捕获特定异常类型
  2. 完整结构:充分利用 try-except-else-finally
  3. 适当记录:使用 logging 记录异常信息
  4. 重试机制:对临时性故障使用重试策略
  5. 资源清理:finally 或 with 语句确保资源释放
  6. 自定义异常:创建业务相关的异常类型
  7. 错误处理:不要忽略异常,要么处理要么重新抛出

这些实践能帮助你编写更健壮、更可维护的 Python 代码。

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