Python 小白 Debug 全指南:从 “看报错就懵” 到 “1 分钟定位 bug”(万字版)

编程达人挑战赛·第6期 10w+人浏览 560人参与

在这里插入图片描述

【个人主页:玄同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 分为两种:

  1. 能运行,但结果不对(比如第一个案例,输出 “area” 而不是 50);
  2. 不能运行,直接崩溃(比如第二个案例,缩进错误)。

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 个:

命令含义大白话翻译
llist:查看当前代码“让我看看现在的代码”
nnext:执行下一行“执行下一步”
sstep in:进入函数“钻进函数里看看”
p 变量名print:打印变量“打印这个变量的值”
qquit:退出调试“退出调试”

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(全流程)

  1. 打开官网:https://www.jetbrains.com/pycharm/download/
  2. 选择 “Community”(社区版,免费),点击下载
  3. 安装时,勾选 “Add Python X.X to PATH”(把 Python 加入系统路径),然后点击 “Next” 直到完成

4.2 PyCharm 的基本操作

4.2.1 新建项目

  1. 打开 PyCharm,点击 “New Project”
  2. 选择项目目录(比如 D:\PythonProject)
  3. 选择 Python 解释器(默认安装的 Python 版本)
  4. 点击 “Create”

4.2.2 新建文件

  1. 右键点击项目目录,选择 “New”→“Python File”
  2. 输入文件名(比如 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("HelloSyntaxError: 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 = 20SyntaxError: 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 流程

  1. 运行代码,输出:
    添加成功!
    添加成功!
    姓名:张三,年龄:student['age']
    删除成功!
    学生不存在!
    
  2. 定位 bug1:search_student 里的 print 少了 f,应该是f"姓名:{student['name']},年龄:{student['age']}"
  3. 修复 bug1,重新运行,输出:
    姓名:张三,年龄:18
    
  4. 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 流程

  1. 运行代码,崩溃,报错 “ZeroDivisionError: division by zero”
  2. 定位 bug1:除以 0 的情况没处理,用 try-except 捕获
  3. 修复 bug1
    elif op == "/":
        try:
            return a / b
        except ZeroDivisionError:
            return "除数不能为0"
    
  4. 重新运行,输出:
    除数不能为0
    20
    
  5. bug2:已经修复!

第八章:小白 Debug 心态调整

  1. bug 是正常的:所有 Python 大佬都是从 “写一行错一行” 过来的,你不是唯一一个;
  2. 错误信息是朋友:它会准确告诉你哪里错了,不要害怕;
  3. 不要瞎改:不要看到错误就乱改代码,要先定位问题;
  4. 从简单到复杂:先写简单的代码,再逐渐复杂,减少 bug;
  5. 多练习:写的代码越多,遇到的 bug 越多,Debug 的速度越快。

总结:Debug 的核心流程

  1. 读报错信息:找到错误类型、位置、原因;
  2. 用 print () 定位:在可疑位置打印变量值;
  3. 用 pdb/PyCharm 一步步运行:看每一步的变量变化;
  4. 查高频 bug 字典:遇到常见 bug 直接查解决方法;
  5. 预防 bug:用 try-except、logging、unittest 减少 bug。

评论 41
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值