跳转至

错误与异常处理

程序在运行过程中不可避免地会遇到错误。Python 提供了强大的异常处理机制,不仅能防止程序崩溃,还能通过捕获错误来进行补救。

1. 错误类型

语法错误 (Syntax Errors)

代码不符合 Python 语法规则,程序根本无法启动

# SyntaxError: unterminated string literal
print("Hello)

异常 (Exceptions)

语法正确,但在运行时发生的错误。如果不处理,程序会中断。

# ZeroDivisionError: division by zero
10 / 0

# FileNotFoundError
open("no_exist.txt")

2. 捕获异常 (try-except)

基本结构

try:
    # 可能发生异常的代码
    num = int(input("请输入数字: "))
    result = 100 / num
    print(f"结果是: {result}")
except ValueError:
    # 捕获输入非数字的情况
    print("错误:请输入有效的数字!")
except ZeroDivisionError:
    # 捕获除以零的情况
    print("错误:不能除以零!")
except Exception as e:
    # 捕获所有其他类型的异常 (兜底)
    print(f"发生未知错误: {e}")

最佳实践

尽量捕获具体的异常类型,而不是泛泛地捕获所有异常 (Exception),这样方便调试和定位问题。

3. 完整的异常结构 (try-except-else-finally)

try:
    f = open("data.txt", "r")
    content = f.read()
except FileNotFoundError:
    print("文件未找到")
else:
    # 只有 try 块没有异常时才执行
    print("读取成功,内容长度:", len(content))
finally:
    #无论是否有异常,都会执行 (常用于资源清理)
    print("关闭文件资源")
    if 'f' in locals():
        f.close()

4. 抛出异常 (raise)

有时我们需要主动触发错误,通知调用者出现了问题。

def check_age(age):
    if age < 0:
        raise ValueError("年龄不能为负数")
    if age > 150:
        raise ValueError("年龄超出合理范围")
    print(f"年龄 {age} 验证通过")

try:
    check_age(-5)
except ValueError as e:
    print(f"验证失败: {e}")

5. 自定义异常

通过继承 Exception 类来定义业务相关的异常。

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

def withdraw(amount, balance):
    if amount > balance:
        raise InsufficientFundsError(f"余额不足: 需 {amount}, 只有 {balance}")
    return balance - amount

try:
    withdraw(100, 50)
except InsufficientFundsError as e:
    print(e)

常见内置异常清单

异常名 描述
IndexError 列表索引超出范围
KeyError 字典中找不到键
TypeError 操作类型不匹配 (如 str + int)
ValueError 参数值不对
AttributeError 对象没有该属性或方法
ImportError 导入模块失败

调试建议 (Debugging)

  1. 阅读 Traceback: 报错信息并不吓人,它会明确告诉你错误在哪一行以及是什么错误
  2. 使用 print 调试: 在关键位置打印变量值。
  3. IDE 断点调试: 在 VS Code 中直接打断点 (F9/F5) 逐行执行,是最最高效的方法。

本章小结

  • try: 放置可能出错的代码。
  • except: 捕获并处理特定错误。
  • else: 若无异常发生时执行。
  • finally: 无论如何都执行(清理善后)。
  • raise: 主动抛出异常。

练习题

  1. 安全除法:编写一个函数 safe_div(a, b),返回 a / b。如果 b 为 0,不报错而是返回 None
  2. 输入验证:循环提示用户输入数字,直到输入正确的数字为止。如果输入非数字,打印提示并继续循环。

下一章:面向对象编程基础