On this page

Python 异常处理

Python 异常处理全面指南

异常处理是Python编程中管理错误和异常情况的重要机制。以下是Python异常处理的详细说明:

1. 异常处理基础

try-except 块

try:
    # 可能引发异常的代码
    result = 10 / 0
except ZeroDivisionError:
    # 处理特定异常
    print("不能除以零!")

基本语法

try:
    # 尝试执行的代码
except ExceptionType:
    # 发生异常时执行的代码
else:
    # 没有异常时执行的代码(可选)
finally:
    # 无论是否发生异常都会执行的代码(可选)

2. 常见异常类型

异常类型描述
Exception所有内置异常的基类
SyntaxError语法错误
NameError未声明/初始化对象
TypeError操作或函数应用于不适当类型
IndexError序列中没有此索引
KeyError映射中没有这个键
ValueError传入无效参数
AttributeError对象没有这个属性
IOError输入/输出操作失败
ZeroDivisionError除(或取模)零
ImportError导入模块/对象失败

3. 异常处理进阶用法

捕获多个异常

try:
    # 可能引发异常的代码
except (TypeError, ValueError) as e:
    print(f"发生类型或值错误: {e}")
except ZeroDivisionError:
    print("发生了除零错误")

捕获所有异常(谨慎使用)

try:
    # 可能引发异常的代码
except Exception as e:
    print(f"发生错误: {e}")

获取异常信息

try:
    10 / 0
except ZeroDivisionError as e:
    print(f"错误类型: {type(e).__name__}")
    print(f"错误信息: {str(e)}")
    print(f"异常对象: {e}")

else 子句

try:
    result = 10 / 2
except ZeroDivisionError:
    print("除零错误")
else:
    print(f"结果是: {result}")  # 仅当没有异常时执行

finally 子句

try:
    file = open("example.txt", "r")
    content = file.read()
except IOError:
    print("文件读取错误")
finally:
    file.close()  # 无论是否发生异常都会执行

4. 主动抛出异常

raise 语句

def validate_age(age):
    if age < 0:
        raise ValueError("年龄不能为负数")
    if age > 120:
        raise ValueError("年龄不合理")

try:
    validate_age(-5)
except ValueError as e:
    print(f"无效年龄: {e}")

自定义异常

class MyCustomError(Exception):
    """自定义异常类"""
    def __init__(self, message):
        self.message = message
        super().__init__(message)

try:
    raise MyCustomError("这是我的自定义错误")
except MyCustomError as e:
    print(e.message)

5. 异常链

Python 3 支持异常链,保留原始异常信息:

try:
    10 / 0
except ZeroDivisionError as e:
    raise ValueError("计算失败") from e

6. 断言(Assertions)

def calculate_average(numbers):
    assert len(numbers) > 0, "列表不能为空"
    return sum(numbers) / len(numbers)

# 断言失败会引发AssertionError

7. 上下文管理器(with语句)

# 文件操作自动处理异常和关闭
try:
    with open("file.txt", "r") as f:
        content = f.read()
except IOError as e:
    print(f"文件操作错误: {e}")

8. 异常处理最佳实践

  1. 具体异常:捕获最具体的异常,而不是笼统的Exception
  2. 最小化try块:只包含可能引发异常的代码
  3. 提供有用信息:异常消息应有助于调试
  4. 避免空except块:至少记录异常信息
  5. 资源清理:使用finally或上下文管理器确保资源释放
  6. 合理使用断言:用于检查不应该发生的情况,而不是常规错误处理

9. 实际应用示例

数据库操作异常处理

import sqlite3

try:
    conn = sqlite3.connect("database.db")
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM users WHERE id=?", (user_id,))
    user = cursor.fetchone()
    if not user:
        raise ValueError("用户不存在")
except sqlite3.DatabaseError as e:
    print(f"数据库错误: {e}")
except ValueError as e:
    print(f"业务逻辑错误: {e}")
except Exception as e:
    print(f"未知错误: {e}")
finally:
    conn.close()  # 确保连接关闭

API请求异常处理

import requests

def fetch_data(url):
    try:
        response = requests.get(url, timeout=5)
        response.raise_for_status()  # 对HTTP错误引发异常
        return response.json()
    except requests.exceptions.Timeout:
        print("请求超时")
    except requests.exceptions.HTTPError as e:
        print(f"HTTP错误: {e.response.status_code}")
    except requests.exceptions.RequestException as e:
        print(f"请求失败: {e}")
    return None

10. 异常处理模式

重试机制

import time

def retry_operation(max_retries=3, delay=1):
    for attempt in range(max_retries):
        try:
            # 可能失败的操作
            return perform_operation()
        except Exception as e:
            if attempt == max_retries - 1:
                raise
            print(f"尝试 {attempt + 1} 失败,重试中...")
            time.sleep(delay)

异常转换

def parse_number(value):
    try:
        return float(value)
    except (TypeError, ValueError) as e:
        raise MyCustomError(f"无法解析 '{value}' 为数字") from e

11. 调试技巧

打印完整异常信息

import traceback

try:
    # 可能出错的代码
except Exception:
    traceback.print_exc()  # 打印完整堆栈跟踪

记录异常

import logging

logging.basicConfig(filename="app.log", level=logging.ERROR)

try:
    # 可能出错的代码
except Exception as e:
    logging.exception("发生异常")

总结

Python异常处理机制提供了强大的错误管理能力:

特性描述
try-except捕获和处理异常
多种异常类型针对不同错误类型特定处理
else子句无异常时执行代码
finally子句确保资源清理
自定义异常创建特定于应用的错误类型
异常链保留原始异常上下文

合理使用异常处理可以使程序更健壮、更易于调试和维护。记住要具体捕获异常、提供有意义的错误信息,并确保资源正确释放。