
【个人主页:玄同765】
大语言模型(LLM)开发工程师|中国传媒大学·数字媒体技术(智能交互与游戏设计)
深耕领域:大语言模型开发 / RAG知识库 / AI Agent落地 / 模型微调
技术栈:Python / LangChain/RAG(Dify+Redis+Milvus)| SQL/NumPy | FastAPI+Docker ️
工程能力:专注模型工程化部署、知识库构建与优化,擅长全流程解决方案
专栏传送门:LLM大模型开发 项目实战指南、Python 从真零基础到纯文本 LLM 全栈实战、从零学 SQL + 大模型应用落地、大模型开发小白专属:从 0 入门 Linux&Shell
「让AI交互更智能,让技术落地更高效」
欢迎技术探讨/项目合作! 关注我,解锁大模型与智能交互的无限可能!
全程零术语、零黑话,用 “小学生能懂的人话” 讲透 Debug,配套30+可直接运行的错误代码示例、20 + 小白高频 bug 汇总、3 个完整实战项目 debug 全流程,帮你彻底解决 “写代码就崩、报错看不懂、改了更崩” 的核心痛点。
引言:为什么你写 Python 总是 “崩溃”?
小白的真实崩溃场景
你刚学会 Python 的 “print ('Hello World!')”,兴冲冲写了第一份 “计算长方形面积” 的代码:
length = 10
width = 5
area = length * width
print("面积是:area") # 这里你打错了!
运行后,程序没报错,但输出是「面积是:area」—— 不是你想要的 50。你盯着代码看了 10 分钟,还是不知道哪里错了。
或者更糟:
if length > 0:
print(“合法”) # 这里没缩进!
运行后,程序直接崩了,弹出一串看不懂的红色文字:
IndentationError: expected an indented block after 'if' statement at line 2
你完全不知道这是什么意思,只能百度,结果搜出来的内容全是 “缩进错误”“语法糖” 这种你听不懂的词,更懵了。
什么是 “bug”?
用大白话讲:bug 就是 “代码的错误”—— 就像你写作文时的 “错别字、病句、没分段”,会导致文章读不通。Python 的 bug 分为两种:
- 能运行,但结果不对(比如第一个案例,输出 “area” 而不是 50);
- 不能运行,直接崩溃(比如第二个案例,缩进错误)。
Debug 的本质:“找错别字的游戏”
Debug 就是 “寻找并修复 bug 的过程”—— 就像你用纠错笔改作文,先找到 “错别字”,再改成正确的内容。
第一章:先学会 “读报错信息”——Python 的 “纠错提示” 不是敌人
1.1 报错信息的 “三段式结构”
所有 Python 的报错信息都遵循固定的三段式,哪怕再长,你只需要看这三部分:
| 部分 | 含义 | 大白话翻译 |
|---|---|---|
| 错误类型 | 比如 SyntaxError、IndentationError | 错误的 “类型”,比如 “语法错了”“缩进错了” |
| 错误位置 | 比如 File "test.py", line 2 | 错误在哪个文件、哪一行 |
| 错误原因 | 比如 expected an indented block | 具体错在哪里 |
示例解析:
Traceback (most recent call last):
File "test.py", line 3, in <module>
print(1 + "2")
TypeError: unsupported operand type(s) for +: 'int' and 'str'
- 错误类型:TypeError(类型错误)
- 错误位置:test.py 第 3 行
- 错误原因:+ 号不能同时用在整数(1)和字符串("2")上
1.2 小白最常遇到的 5 种核心错误(配代码 + 解决)
1.2.1 IndentationError(缩进错误)——“写作文没分段”
错误代码:
if 5 > 3:
print("5比3大") # 这里没有缩进!
错误信息:
IndentationError: expected an indented block after 'if' statement at line 1
原因:Python 是 “缩进敏感” 的语言 —— 就像写作文,“如果……” 后面的内容要 “空两格 / 4 个空格”,否则算 “没分段”。解决方法:在 print 前面加4 个空格(或按一下 Tab 键,但要统一用一种方式):
if 5 > 3:
print("5比3大") # 正确缩进
1.2.2 NameError(变量未定义)——“说一个不存在的词”
错误代码:
x = 10
print(y) # 你没定义过y!
错误信息:
NameError: name 'y' is not defined
原因:你用了一个 “没起过名字的变量”—— 就像你跟别人说 “那个红色的东西”,但你从来没提过 “红色的东西是什么”。解决方法:要么定义 y,要么把 y 改成 x:
x = 10
print(x) # 正确
1.2.3 TypeError(类型错误)——“用刀叉吃稀饭”
错误代码:
a = 10 # 整数
b = "20" # 字符串
print(a + b) # 用+把不同类型的东西加在一起!
错误信息:
TypeError: unsupported operand type(s) for +: 'int' and 'str'
原因:不同类型的变量不能用同一操作符 —— 就像你用刀叉吃稀饭,工具不对。解决方法:把它们转成同一个类型:
a = 10
b = 20 # 转成整数
print(a + b) # 30(正确)
# 或
a = "10" # 转成字符串
b = "20"
print(a + b) # 1020(正确,字符串拼接)
1.2.4 SyntaxError(语法错误)——“说话没标点”
错误代码:
print("Hello World) # 少了一个引号!
错误信息:
SyntaxError: EOL while scanning string literal
原因:Python 的语法有 “固定格式”—— 就像说话要加标点,否则别人听不懂。这里少了一个双引号。解决方法:补全引号:
print("Hello World") # 正确
1.2.5 ValueError(值错误)——“把苹果当香蕉吃”
错误代码:
x = int("abc") # 把字母转成整数!
错误信息:
ValueError: invalid literal for int() with base 10: 'abc'
原因:你给了函数一个 “它处理不了的值”—— 就像你让卖水果的把苹果当成香蕉卖给你,他做不到。解决方法:给 int () 传数字字符串:
x = int("123") # 正确
第二章:基础 Debug 神器 ——print ()“打酱油法”
print () 是 Python 小白最容易上手、最实用的 Debug 工具 —— 没有之一。它的原理是 “在代码的关键位置打印变量的值,看哪里和你预期的不一样”。
2.1 print () 的正确用法
错误用法:只打印变量本身:
x = 10
y = 20
z = x + y
print(z) # 30,但你不知道x和y是不是你想的10和20
正确用法:打印 “变量名 + 变量值”,让你知道哪个变量出问题:
x = 10
print("x的值是:", x) # 打印:x的值是: 10
y = 20
print("y的值是:", y) # 打印:y的值是: 20
z = x + y
print("z的值是:", z) # 打印:z的值是: 30
2.2 用 print () 找 bug 的完整流程
案例需求:写一个 “计算两个数平均数” 的函数,但运行结果不对。错误代码:
def average(a, b):
result = (a + b) / 0 # 你不小心把2写成了0!
return result
num1 = 10
num2 = 20
print(average(num1, num2))
运行结果:崩溃,报错 “ZeroDivisionError: division by zero”(除以 0 错误)。
步骤 1:定位错误位置
从报错信息看,错误在 “(a + b) / 0” 这一行 —— 除以 0 了。
步骤 2:用 print () 验证变量
你可能会想 “是不是 a 或 b 是 0?”,用 print () 验证:
def average(a, b):
print("a的值是:", a) # 打印a
print("b的值是:", b) # 打印b
print("a + b的值是:", a + b) # 打印a+b
result = (a + b) / 0
return result
num1 = 10
num2 = 20
print(average(num1, num2))
运行结果:
a的值是: 10
b的值是: 20
a + b的值是: 30
ZeroDivisionError: division by zero
结果显示 a 和 b 都是对的,问题在 “除以 0”—— 你把 “除以 2” 写成了 “除以 0”!
步骤 3:修复 bug
把 0 改成 2:
def average(a, b):
result = (a + b) / 2 # 正确
return result
print(average(10, 20)) # 15.0(正确)
2.3 print () 的高级用法:格式化输出(可选)
如果变量多,你可以用f-string(Python3.6+)格式化输出,更清晰:
x = 10
y = 20
print(f"x的值是:{x},y的值是:{y}") # 打印:x的值是:10,y的值是:20
第三章:进阶 Debug 工具 ——pdb(Python 自带调试器)
print () 虽然简单,但如果代码很长(比如 100 行),需要打很多 print,非常麻烦。这时候可以用 Python自带的 pdb 调试器—— 不用装任何东西,直接在命令行里一步步运行代码,看每一步的变量变化。
3.1 pdb 的基本命令
pdb 的命令非常简单,只需要记 5 个:
| 命令 | 含义 | 大白话翻译 |
|---|---|---|
l | list:查看当前代码 | “让我看看现在的代码” |
n | next:执行下一行 | “执行下一步” |
s | step in:进入函数 | “钻进函数里看看” |
p 变量名 | print:打印变量 | “打印这个变量的值” |
q | quit:退出调试 | “退出调试” |
3.2 pdb 的使用步骤
案例需求:写一个 “递归计算阶乘” 的函数,但结果不对。错误代码:
def factorial(n):
if n == 1:
return 1
else:
return n * factorial(n + 1) # 你把n-1写成了n+1!
print(factorial(5)) # 应该是120,结果会崩溃
步骤 1:用 pdb 启动代码
在命令行里输入(注意文件名是 test.py):
python -m pdb test.py
启动后会看到:
> test.py(1)<module>()
-> def factorial(n):
步骤 2:执行下一行(n 命令)
输入n,按回车 —— 执行第 1 行(def 定义函数):
> test.py(8)<module>()
-> print(factorial(5))
步骤 3:进入函数(s 命令)
输入s,按回车 —— 钻进 factorial (5) 函数里:
> test.py(2)factorial()
-> if n == 1:
步骤 4:打印变量(p 命令)
输入p n,按回车 —— 看 n 的值:
5
步骤 5:继续执行(n 命令)
输入n——n 不是 1,执行 else 部分:
> test.py(5)factorial()
-> return n * factorial(n + 1)
步骤 6:发现问题
输入p n + 1—— 看 n+1 的值:
6
你发现问题了!阶乘应该是factorial(n - 1),你写成了factorial(n + 1)—— 这样 n 会越来越大,永远不会等于 1,导致程序崩溃。
步骤 7:退出调试(q 命令)
输入q,按回车,退出调试。
步骤 8:修复 bug
把 n+1 改成 n-1:
def factorial(n):
if n == 1:
return 1
else:
return n * factorial(n - 1) # 正确
print(factorial(5)) # 120(正确)
第四章:可视化 Debug——PyCharm(小白友好的图形界面)
如果命令行的 pdb 对你来说太 “黑科技”,可以用PyCharm(社区版,免费)—— 图形界面的调试器,点点按钮就能一步步运行代码,看变量变化。
4.1 安装 PyCharm(全流程)
- 打开官网:https://www.jetbrains.com/pycharm/download/
- 选择 “Community”(社区版,免费),点击下载
- 安装时,勾选 “Add Python X.X to PATH”(把 Python 加入系统路径),然后点击 “Next” 直到完成
4.2 PyCharm 的基本操作
4.2.1 新建项目
- 打开 PyCharm,点击 “New Project”
- 选择项目目录(比如 D:\PythonProject)
- 选择 Python 解释器(默认安装的 Python 版本)
- 点击 “Create”
4.2.2 新建文件
- 右键点击项目目录,选择 “New”→“Python File”
- 输入文件名(比如 test.py),点击 “Enter”
4.3 PyCharm 的 Debug 操作(配案例)
案例需求:写一个 “计算斐波那契数列” 的函数,结果不对。错误代码:
def fib(n):
if n <= 0:
return 0
elif n == 1:
return 1
else:
return fib(n - 1) + fib(n - 3) # 你把n-2写成了n-3!
print(fib(10)) # 应该是55,结果是34
步骤 1:设置断点
在代码的第 6 行(return fib (n - 1) + fib (n - 3))左边点击一下,会出现一个红色圆点 —— 这就是 “断点”:程序运行到这里会自动停下。
步骤 2:启动 Debug
点击 PyCharm 右上角的 “虫子” 图标(或按 Shift+F9),启动 Debug。
步骤 3:看变量变化
启动后,程序会在断点处停下,右边的 “Variables” 窗口会显示所有变量的值:
- n 的值是 10
- 你可以看到 fib (n-1) 是 fib (9),fib (n-3) 是 fib (7)—— 这就是错误的地方!
步骤 4:修复 bug
把 n-3 改成 n-2,点击 “虫子” 图标重新运行,结果是 55(正确)。
第五章:小白高频 bug 汇总
这部分是小白的 “纠错字典”,遇到 bug 直接查就能找到解决方法:
5.1 语法与格式错误
| 错误代码 | 错误信息 | 原因 | 解决方法 |
|---|---|---|---|
print("Hello | SyntaxError: EOL while scanning string literal | 少了双引号 | 补全双引号:print("Hello") |
if 5>3: print("5>3") | (Python3.8 + 允许,但不推荐) | 一行写了多行代码 | 分成两行,加缩进 |
print(1,2) print(3,4) | SyntaxError: invalid syntax | 没有换行 | 两行之间加换行 |
x = 10 y = 20 | SyntaxError: invalid syntax | 没有换行 | 分成两行 |
5.2 变量与类型错误
| 错误代码 | 错误信息 | 原因 | 解决方法 |
|---|---|---|---|
print(X) | NameError: name 'X' is not defined | 变量名大小写错误 | 改成print(x) |
1 + "2" | TypeError: unsupported operand type(s) for +: 'int' and 'str' | 类型不匹配 | 转成同一类型:1 + int("2") |
int("3.14") | ValueError: invalid literal for int() with base 10: '3.14' | 浮点数转整数 | 用float("3.14")或int(3.14) |
list[0] | NameError: name 'list' is not defined | 变量名用了关键字 | 改成my_list[0] |
5.3 函数与模块错误
| 错误代码 | 错误信息 | 原因 | 解决方法 |
|---|---|---|---|
def func(a,b): return a + b; func(1) | TypeError: func() missing 1 required positional argument: 'b' | 少传参数 | 传两个参数:func(1,2) |
import numpy; np.array([1,2]) | NameError: name 'np' is not defined | 没有别名 | 改成import numpy as np |
from math import pi; print(Pi) | NameError: name 'Pi' is not defined | 大小写错误 | 改成print(pi) |
func(a=1, 2) | SyntaxError: positional argument follows keyword argument | 位置参数在关键字参数后面 | 改成func(2, a=1)或func(1, 2) |
第六章:高级 Debug 技巧(小白可以跳过,但建议了解)
6.1 日志调试 —— 用 logging 模块
当你写的代码需要长期运行(比如服务器),print () 会导致日志太多,这时候可以用logging 模块—— 可以设置日志级别(DEBUG/INFO/ERROR),只保存重要的日志。
基本用法:
import logging
# 配置日志
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s")
# 用日志代替print
logging.debug("x的值是:10") # DEBUG级别
logging.info("程序开始运行") # INFO级别
logging.error("发生错误") # ERROR级别
# 输出:
# 2024-05-20 14:30:00,123 - DEBUG - x的值是:10
# 2024-05-20 14:30:00,124 - INFO - 程序开始运行
# 2024-05-20 14:30:00,125 - ERROR - 发生错误
6.2 错误捕获 ——try-except
有时候你知道代码可能会出错,但不想让它崩溃,可以用try-except捕获错误,做一些处理(比如提示用户输入错误)。
基本用法:
try:
x = int(input("请输入一个整数:")) # 可能会输入非整数
print("你输入的是:", x)
except ValueError:
print("你输入的不是整数!请重新输入!")
运行结果:
- 输入 123:打印 “你输入的是:123”
- 输入 abc:打印 “你输入的不是整数!请重新输入!”
6.3 单元测试 —— 用 unittest
当你写的代码很复杂时,可以用unittest 模块—— 写一些 “测试用例”,自动检查代码是否正确。
基本用法:
import unittest
def add(a, b):
return a + b
class TestAdd(unittest.TestCase):
def test_add(self):
self.assertEqual(add(1, 2), 3) # 检查add(1,2)是否等于3
if __name__ == "__main__":
unittest.main()
运行结果:
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
第七章:实战项目 Debug 全流程(3 个案例)
7.1 案例 1:学生管理系统
需求:写一个学生管理系统,实现 “添加学生、查询学生、删除学生” 功能。错误代码(留了 3 个 bug):
# 学生管理系统
students = []
def add_student(name, age):
student = {"name": name, "age": age}
students.append(student)
print("添加成功!")
def search_student(name):
for student in students:
if student["name"] == name:
print(f"姓名:{student['name']},年龄:student['age']") # bug1:少了f
return
print("学生不存在!")
def delete_student(name):
for student in students:
if student["name"] == name:
students.remove(student)
print("删除成功!")
return
print("学生不存在!")
# 测试
add_student("张三", 18)
add_student("李四", 19)
search_student("张三") # bug2:输出不对
delete_student("李四")
search_student("李四") # bug3:输出不对
Debug 流程
- 运行代码,输出:
添加成功! 添加成功! 姓名:张三,年龄:student['age'] 删除成功! 学生不存在! - 定位 bug1:search_student 里的 print 少了 f,应该是
f"姓名:{student['name']},年龄:{student['age']}" - 修复 bug1,重新运行,输出:
姓名:张三,年龄:18 - bug2:delete_student 的功能是对的,因为李四被删除了,所以 search_student 找不到,输出 “学生不存在” 是对的 —— 没有 bug!
7.2 案例 2:计算器
需求:写一个计算器,实现 “加、减、乘、除” 功能。错误代码(留了 2 个 bug):
# 计算器
def calculate(a, b, op):
if op == "+":
return a + b
elif op == "-":
return a - b
elif op == "*":
return a * b
elif op == "/":
return a / b # bug1:没处理除以0
else:
return "无效操作符"
# 测试
print(calculate(10, 0, "/")) # bug2:会崩溃
print(calculate(10, 2, "*")) # 应该是20
Debug 流程
- 运行代码,崩溃,报错 “ZeroDivisionError: division by zero”
- 定位 bug1:除以 0 的情况没处理,用 try-except 捕获
- 修复 bug1:
elif op == "/": try: return a / b except ZeroDivisionError: return "除数不能为0" - 重新运行,输出:
除数不能为0 20 - bug2:已经修复!
第八章:小白 Debug 心态调整
- bug 是正常的:所有 Python 大佬都是从 “写一行错一行” 过来的,你不是唯一一个;
- 错误信息是朋友:它会准确告诉你哪里错了,不要害怕;
- 不要瞎改:不要看到错误就乱改代码,要先定位问题;
- 从简单到复杂:先写简单的代码,再逐渐复杂,减少 bug;
- 多练习:写的代码越多,遇到的 bug 越多,Debug 的速度越快。
总结:Debug 的核心流程
- 读报错信息:找到错误类型、位置、原因;
- 用 print () 定位:在可疑位置打印变量值;
- 用 pdb/PyCharm 一步步运行:看每一步的变量变化;
- 查高频 bug 字典:遇到常见 bug 直接查解决方法;
- 预防 bug:用 try-except、logging、unittest 减少 bug。

1325





