异常处理

前言

异常处理是编写健壮程序的关键。本章介绍如何捕获和处理异常。

什么是异常

异常是在程序执行期间发生的错误。Python 使用异常对象表示错误。

# 可能引发异常的代码
result = 10 / 0  # ZeroDivisionError

try-except 语句

try:
    # 可能引发异常的代码
    result = 10 / 0
except ZeroDivisionError:
    # 处理特定异常
    print("Cannot divide by zero!")

捕获多个异常

try:
    num = int(input("Enter a number: "))
    result = 10 / num
except ValueError:
    print("Invalid input! Please enter a number.")
except ZeroDivisionError:
    print("Cannot divide by zero!")
except Exception as e:
    print(f"An unexpected error occurred: {e}")

else 和 finally 子句

try:
    file = open("example.txt", "r")
    content = file.read()
except FileNotFoundError:
    print("File not found")
else:
    # 只有在没有异常时执行
    print("File read successfully")
    print(f"Content length: {len(content)}")
finally:
    # 总是执行(无论是否异常)
    if 'file' in locals():
        file.close()
    print("Cleanup completed")

抛出异常

def divide(a, b):
    if b == 0:
        raise ValueError("Cannot divide by zero")
    return a / b

try:
    result = divide(10, 0)
except ValueError as e:
    print(e)

自定义异常

class InsufficientFundsError(Exception):
    """自定义异常:余额不足"""
    pass

class BankAccount:
    def __init__(self, balance):
        self.balance = balance

    def withdraw(self, amount):
        if amount > self.balance:
            raise InsufficientFundsError("Insufficient funds")
        self.balance -= amount
        return amount

try:
    account = BankAccount(100)
    account.withdraw(150)
except InsufficientFundsError as e:
    print(e)

异常层次结构

Python 异常形成层次结构:

  • BaseException(所有异常的基类)
    • Exception(常规异常)
      • ValueError, TypeError, FileNotFoundError 等
    • SystemExit, KeyboardInterrupt 等
try:
    # 一些代码
    pass
except Exception:
    # 捕获所有常规异常
    print("An error occurred")

断言 (assert)

用于调试,确保条件为真。

def divide(a, b):
    assert b != 0, "Cannot divide by zero"
    return a / b

divide(10, 0)  # AssertionError: Cannot divide by zero

日志记录

比 print 更好的错误记录方式。

import logging

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

try:
    result = 10 / 0
except ZeroDivisionError:
    logging.error("Division by zero attempted")

常见异常类型

  • ValueError: 值错误(如 int("abc"))
  • TypeError: 类型错误(如 "hello" + 5)
  • IndexError: 索引超出范围
  • KeyError: 字典键不存在
  • FileNotFoundError: 文件不存在
  • ZeroDivisionError: 除零错误
  • AttributeError: 属性不存在

最佳实践

  1. 只捕获你能处理的异常
  2. 保持异常处理简单
  3. 使用 finally 进行清理
  4. 提供有意义的错误信息
  5. 考虑使用日志而不是 print

本章小结

  • 使用 try-except 捕获异常
  • else 子句在无异常时执行,finally 总是执行
  • 可以抛出和自定义异常
  • 了解常见异常类型和最佳实践

练习题

  1. 编写一个函数,安全地进行除法运算,处理除零错误。
  2. 创建一个自定义异常类,并在一个函数中使用它。
  3. 编写一个程序,读取文件并处理可能的异常。
  4. 使用断言验证函数参数的有效性。
posted on 2026-05-05 22:04  小樊童鞋  阅读(8)  评论(0)    收藏  举报