Skip to content

08 异常处理

📋 资料说明

  • 来源:课程 day08
  • 笔记尚硅谷大模型技术之Python1.0.docx 第 9 章
  • 每日一考day08_每日一考.mdday08_20251030周四考试.md(含周考题目)
  • 视频:❌ 跳过(共 11 个视频:异常介绍 → 处理不同类型 → else/finally → raise/assert/with → 自定义异常)

🟢 🤖 AI 替代率:97%

为什么是这个水平:

异常处理语法非常固定:try-except-else-finally 结构和 raise/assert 都是确定性规则。AI 可以准确生成各种异常处理场景的代码。

唯一需要人工判断的是:应该捕获什么异常。捕获太宽(except Exception)会掩盖 bug,捕获太窄(except ValueError)可能漏掉其他异常。但这个判断属于「经验不足 AI 也能设计好"合理"的捕获范围」,影响不大。


👤 人工干预率:3%

几乎无需干预。——了解 try-except-else-finally 的执行顺序和资源清理的 with 语句即可。


1. try-except 基本使用

python
try:
    # 可能出错的代码
    num = int(input("输入数字: "))
    result = 10 / num
    print(f"结果是: {result}")
except ValueError:
    print("输入的不是数字")
except ZeroDivisionError:
    print("不能除以零")

捕获多种异常

python
try:
    num = int(input("输入数字: "))
    result = 10 / num
except (ValueError, ZeroDivisionError) as e:
    print(f"出错: {e}")

捕获所有异常(不推荐)

python
try:
    # 某些操作
    pass
except Exception as e:
    print(f"发生错误: {e}")
# 不要用裸 except: ——会捕获 KeyboardInterrupt 等系统异常

2. else 和 finally

python
try:
    num = int(input("输入数字: "))
    result = 10 / num
except ValueError:
    print("输入的不是数字")
except ZeroDivisionError:
    print("不能除以零")
else:
    # 没有异常时才执行
    print(f"计算成功: {result}")
finally:
    # 不管有没有异常都执行
    print("程序结束")

# 执行顺序:try → else(无异常时)→ finally
#         try → except(有异常时)→ finally

finally 的典型用途

python
# 资源清理
f = None
try:
    f = open("test.txt", "r")
    content = f.read()
except FileNotFoundError:
    print("文件不存在")
finally:
    if f:
        f.close()  # 确保文件关闭

3. raise 抛出异常

python
def withdraw(balance, amount):
    if amount <= 0:
        raise ValueError("取款金额必须为正数")
    if amount > balance:
        raise ValueError("余额不足")
    return balance - amount

try:
    new_balance = withdraw(100, 200)
except ValueError as e:
    print(f"取款失败: {e}")

自定义异常

python
class InsufficientBalanceError(Exception):
    """余额不足异常"""
    def __init__(self, balance, amount):
        self.balance = balance
        self.amount = amount
        super().__init__(f"余额 {balance},需要 {amount},差额 {amount - balance}")

def withdraw(balance, amount):
    if amount > balance:
        raise InsufficientBalanceError(balance, amount)
    return balance - amount

try:
    withdraw(100, 200)
except InsufficientBalanceError as e:
    print(e)  # 余额 100,需要 200,差额 100

4. assert 断言

python
# assert 条件, "错误信息"
# 条件为 False 时抛出 AssertionError

def divide(a, b):
    assert b != 0, "除数不能为零"
    return a / b

divide(10, 2)   # 5.0
# divide(10, 0)  # AssertionError: 除数不能为零

assert 与 raise 的区别

  • assert:用于开发和调试阶段的"合约检查",可被 python -O script.py 优化掉
  • raise:用于生产环境的异常处理

5. 异常的传递

python
def func1():
    print("func1 开始")
    raise ValueError("func1 出错")

def func2():
    print("func2 开始")
    func1()
    print("func2 结束")  # 不会执行

try:
    func2()
except ValueError as e:
    print(f"捕获到: {e}")

# 输出:
# func2 开始
# func1 开始
# 捕获到: func1 出错

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

python
# with 自动管理资源的获取和释放
# 任何实现了 __enter__ 和 __exit__ 方法的对象都可以用 with

# 文件操作(最常用的场景)
with open("test.txt", "w") as f:
    f.write("Hello")

# 自定义上下文管理器
class ManagedResource:
    def __enter__(self):
        print("获取资源")
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("释放资源")
        return False  # 返回 False 表示不屏蔽异常
    
    def do_something(self):
        print("使用资源")

with ManagedResource() as res:
    res.do_something()
# 输出:
# 获取资源
# 使用资源
# 释放资源

练习题

练习 1:输入验证

编写一个函数,接受用户输入的整数,如果输入不是数字则提示重新输入,直到输入正确为止。

练习 2:文件安全读取

读取一个可能不存在的文件,如果不存在则创建并写入默认内容。

练习 3:自定义异常

定义一个 NegativeNumberError 异常类,当计算平方根时传入负数时抛出。


参考答案

练习 1:

python
def get_integer(prompt):
    while True:
        try:
            return int(input(prompt))
        except ValueError:
            print("请输入一个有效的整数")

num = get_integer("输入数字: ")
print(f"你输入了: {num}")

练习 2:

python
def safe_read(filename, default="默认内容"):
    try:
        with open(filename, "r", encoding="utf-8") as f:
            return f.read()
    except FileNotFoundError:
        with open(filename, "w", encoding="utf-8") as f:
            f.write(default)
        return default

content = safe_read("config.txt")
print(content)

练习 3:

python
class NegativeNumberError(Exception):
    pass

import math
def sqrt_positive(n):
    if n < 0:
        raise NegativeNumberError("不能对负数开平方")
    return math.sqrt(n)

try:
    print(sqrt_positive(-4))
except NegativeNumberError as e:
    print(e)

OPC 超级个体实战指南