编程启蒙|Scratch 转 Python 系列第 13 天:异常处理 try/except 积木双向对照(AI 接口调用容错实战)
一、本篇摘要
你在 Day 7 猜数字游戏里应该遇到过:用户输入 “abc” 直接程序崩溃。在 Day 11 文件读写里也遇到过:文件不存在直接报错。今天我们就学一个 Python 独有的工程能力——异常处理,让程序在遇到"意外"时优雅兜底,而不是一脚踩空崩溃退出。
这也是 AI API 调用的必备技能:网络卡住、Key 过期、返回格式错——都靠 try/except 兜住。
二、本节课学习目标
- 理解异常是什么、为什么会有异常,掌握 Python 五种最常见的异常类型。
- 掌握
try/except/else/finally四段式结构,知道每段各自的用途和执行时机。 - 学会
raise主动抛出异常,以及自定义异常类,让代码错误信息更清晰。 - 完成一个AI API 调用重试机制——网络失败自动重试 3 次,理解生产级代码为什么必须写异常处理。
三、专业名词通俗释义
| 专业名词 | 通俗解释 |
|---|---|
异常(Exception) |
程序运行时的"意外",如输入非法、除零、文件不存在 |
抛出异常(raise) |
程序主动说"这里出错了" |
捕获异常(except) |
用 try 把可能出错的代码"包起来",出错时进入 except 处理 |
finally 块 |
无论有没有异常,一定会执行的收尾代码(比如关文件) |
| 自定义异常 | 自己写一个异常类,让报错信息更贴合业务场景 |
四、分模块双向对照
模块 1:什么是异常——先看看崩溃现场
# 场景 1:类型转换错误
num = int("abc") # ValueError: invalid literal
# 场景 2:除零错误
result = 10 / 0 # ZeroDivisionError
# 场景 3:文件不存在
f = open("not_exist.txt") # FileNotFoundError
# 场景 4:字典键不存在
d = {"a": 1}
d["b"] # KeyError: 'b'
# 场景 5:索引越界
lst = [1, 2, 3]
lst[10] # IndexError: list index out of range
Scratch 里没有对应积木——Scratch 遇到错误会默默无视(比如 列表第100项 直接返回空)。Python 的严格是特点,也是这一课要解决的问题。
模块 2:try/except 基础捕获

# 【Scratch积木】如果 <出错> 那么 说 "错了,别慌",否则继续
# ↑ Scratch 没有对应积木,Python 的 try/except 是升级版
try:
num = int(input("请输入一个数字:"))
print(f"你输入的是 {num}")
except ValueError:
print("⚠️ 你输的不是数字,别捣乱")
print("程序继续运行...") # 即使上面出错也能到这里
核心易错说明:except 后面接的是异常类名,指定错什么才捕获;不指定则捕获所有——但不推荐,会掩盖真正的 bug。
模块 3:多个 except 精细处理
try:
a = int(input("被除数:"))
b = int(input("除数:"))
print(a / b)
except ValueError:
print("⚠️ 请输入数字")
except ZeroDivisionError:
print("⚠️ 除数不能为 0")
except Exception as e:
print(f"⚠️ 意外错误:{e}")
核心易错说明:从具体到通用排列——ValueError 在前,Exception(万能兜底)在后;否则具体异常永远进不到。
模块 4:else + finally 完整四段式
try:
f = open("data.txt", "r", encoding="utf-8")
content = f.read()
except FileNotFoundError:
print("⚠️ 文件不存在")
else:
# 【Scratch积木】没出错才执行
print("✅ 读取成功")
print(content)
finally:
# 【Scratch积木】不管出没出错,都要执行(收尾/清理)
print("🔚 处理结束")
执行时机对照表:
| 段 | 什么时候执行 |
|---|---|
try |
一直执行到出错或结束 |
except |
只在出错时执行 |
else |
只在 try 没出错时执行 |
finally |
无论如何都执行(用于关闭文件、断开连接) |
模块 5:raise 主动抛出异常

# 【Scratch积木】如果 <年龄 < 0> 那么 说 "年龄非法",停止该脚本
def set_age(age):
if age < 0:
raise ValueError(f"年龄不能是负数:{age}")
if age > 150:
raise ValueError(f"年龄过大:{age}")
return age
try:
set_age(-5)
except ValueError as e:
print(f"❌ 参数错误:{e}")
使用场景:函数收到非法参数时,主动 raise 比"默默返回 None"更好——错误更明显,方便排查。
模块 6:自定义异常类(进阶)

# 【Scratch积木】新建自定义积木「AI 调用失败异常」
class AIAPIError(Exception):
"""AI 接口调用失败的自定义异常"""
pass
class RateLimitError(AIAPIError):
"""调用频率超限"""
pass
def call_ai_api(prompt):
# 假装调用 AI 时被限流
raise RateLimitError("每分钟调用超过 100 次,请稍后重试")
try:
call_ai_api("你好")
except RateLimitError as e:
print(f"🚦 限流:{e}")
except AIAPIError as e:
print(f"🤖 API 通用错误:{e}")
核心易错说明:自定义异常必须继承 Exception(或其子类);类名后必须接冒号和 pass 或文档字符串。
五、综合实战项目:AI API 调用重试机制
项目目标:模拟一个不稳定的 AI 接口(30% 概率随机失败),用 try/except 实现自动重试 3 次——这是所有生产级 AI 应用的最小容错内核。
Scratch 积木流程:
- 重复执行 3 次(最多重试次数)
- try 调用 AI 接口
- 成功 → 返回结果并跳出
- 失败 → 打印重试提示 → 继续下一次
- 3 次都失败 → 抛出最终异常

Python 完整可运行源码:
import random
import time
# 【Scratch积木】自定义异常
class AIAPIError(Exception):
"""AI 调用失败"""
pass
# 【Scratch积木】定义积木 fake_ai_call(prompt) → 30% 概率失败
def fake_ai_call(prompt):
"""模拟一个不稳定的 AI 接口"""
if random.random() < 0.3:
raise AIAPIError("网络超时或服务繁忙")
return f"[AI 回答] 我收到了你的问题:{prompt}"
# 【Scratch积木】定义积木 call_with_retry(prompt, max_retry)
def call_with_retry(prompt, max_retry=3):
"""带重试机制的 AI 调用"""
for attempt in range(1, max_retry + 1):
try:
print(f"🚀 第 {attempt} 次调用中...")
result = fake_ai_call(prompt)
print(f"✅ 成功!")
return result
except AIAPIError as e:
print(f"⚠️ 第 {attempt} 次失败:{e}")
if attempt < max_retry:
wait = 2 ** attempt # 指数退避:2s、4s、8s
print(f" ⏳ 等待 {wait} 秒后重试...")
time.sleep(wait)
except Exception as e:
print(f"❌ 未知错误:{e}")
raise
# 【Scratch积木】三次都失败 → 抛出最终异常
raise AIAPIError(f"重试 {max_retry} 次后仍失败")
# 【Scratch积木】主入口
def main():
print("=" * 40)
print(" 🤖 AI 调用重试机制演示")
print("=" * 40)
while True:
prompt = input("\n请输入问题(q 退出):").strip()
if prompt.lower() == "q":
break
try:
answer = call_with_retry(prompt, max_retry=3)
print(f"\n💬 {answer}")
except AIAPIError as e:
print(f"\n💔 最终失败:{e}")
print("💡 建议:检查网络或稍后再试")
if __name__ == "__main__":
main()
运行方式:保存为 day13_code.py → 命令行 python day13_code.py → 观察 30% 概率失败时的自动重试过程。
💡 这个模式在真实工作里到处都是:调用大模型 API、爬网页、连数据库、发短信——只要涉及外部服务,就必然要写重试。今天孩子学的 20 行代码,就是所有互联网工程师每天都在写的模式。
六、高频易错点总结
1. except: 什么都不写,捕获所有异常
会吃掉真正的 bug——比如变量拼写错也被吞掉。永远显式写异常类型,最多兜底加一层 except Exception as e。
2. try 里包太多行
一个 try 里 20 行代码,出错时不知道到底哪一行出的错。try 里只包"真正可能出错的那几行"。
3. except 里 pass 直接吞掉错误
看起来"程序不崩了",其实掩盖了问题。至少要打印错误信息,或者写日志。
4. 忘记 finally 关闭资源
打开的文件、数据库连接、网络端口,没关就"泄漏"——用 finally 或 with 语句双保险。
5. 自定义异常忘记继承 Exception
class MyError: 不继承的话根本不是异常,raise 会报错。必须 class MyError(Exception):。
七、💡 学习提示
为鼓励大家动手练习、吃透编程逻辑,本篇不提供 Scratch 成品源码,请对照截图亲手搭建积木完成复刻!
配套 Python 代码可直接复制运行学习。
八、往期历史笔记
-
编程启蒙|Scratch 转 Python 系列第 3 天:循环重复积木双向对照(AI 批量循环处理,已收录 AI Agent 技术社区)
-
编程启蒙|Scratch 转 Python 系列第 5 天:自定义积木 / 函数双向对照(AI 工具封装、重复指令简化实战)
-
编程启蒙|Scratch 转 Python 系列第 6 天:列表、数组积木双向对照(AI 底层语法 / AI 批量数据处理实战)
-
编程启蒙|Scratch 转 Python 系列第 7 天:猜数字大挑战·升级版实战(AI 出题 + 二分查找最优解 + 完整命令行游戏 已被收录在智能体开发者社区)
-
编程启蒙|Scratch 转 Python 系列第 12 天:记忆翻牌游戏实战(AI 图案主题包 + 存档排行榜 已被收录在2048 AI社区)
九、下一章预告
Scratch 转 Python 系列第 14 天:AI 提示词管理工具实战(增删改查 + 存档导入 + 异常兜底)
一个可实际使用的命令行 AI 提示词工具,串联 Day 6 列表 + Day 9 字典 + Day 11 文件 + 本篇异常处理——用来管理你自己的 AI Prompt 素材库。
十、原创声明
本文为**「梅雅达编程笔记」**原创启蒙教程,禁止私自搬运、二次转载,转发请标注来源。
想要系统学完整套 Scratch 转 Python 课程,欢迎订阅下方专栏持续追更。
更多推荐



所有评论(0)