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

在这里插入图片描述

【个人主页:玄同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. 定位 bug1:search_student 里的 print 少了 f,应该是f"姓名:{student['name']},年龄:{student['age']}"
  2. bug2:delete_student 的功能是对的,因为李四被删除了,所以 search_student 找不到,输出 “学生不存在” 是对的 —— 没有 bug!

修复 bug1,重新运行,输出:

姓名:张三,年龄:18 

运行代码,输出:

添加成功! 添加成功! 姓名:张三,年龄:student['age'] 删除成功! 学生不存在! 

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. bug2:已经修复!

重新运行,输出:

除数不能为0 20 

修复 bug1

elif op == "/": try: return a / b except ZeroDivisionError: return "除数不能为0" 

第八章:小白 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。

Read more

Python EXE逆向分析终极指南:3步完成代码提取

Python EXE逆向分析终极指南:3步完成代码提取 【免费下载链接】python-exe-unpacker 项目地址: https://gitcode.com/gh_mirrors/pyt/python-exe-unpacker Python EXE Unpacker是一款专为逆向分析Python可执行文件设计的强大工具,能够快速提取PyInstaller和py2exe封装的EXE文件中的源代码。无论您是安全研究人员还是开发者,这款解压工具都能帮助您轻松完成逆向分析任务,揭示封装Python程序的内部逻辑。 🚀 为什么需要Python EXE解压工具? 在日常开发和安全分析中,经常会遇到需要分析Python打包的EXE文件的情况。Python EXE Unpacker提供了简单高效的解决方案: * 安全审计:快速分析可疑Python程序,发现潜在威胁 * 代码恢复:帮助找回丢失的源代码文件 * 学习研究:深入了解Python打包机制和逆向工程原理 核心功能亮点 * 智能识别:自动检测EXE文件使用的打包工具(PyInstaller或py2exe) * 一

By Ne0inhk
Python + uiautomator2 手机自动化控制教程

Python + uiautomator2 手机自动化控制教程

简介 uiautomator2 是比 ADB 更强大的 Android 自动化框架,支持元素定位、控件操作、应用管理等高级功能。本教程适合需要更精细控制的开发者。 一、环境准备 1.1 前置要求 * Python 3.6 或更高版本 * Android 手机(需开启开发者模式和 USB 调试) * USB 数据线 * 已安装 ADB 工具(参考第一篇教程) 1.2 检查 Python 环境 python --version # 应显示 Python 3.6 或更高版本 1.3 检查 ADB 连接 adb devices

By Ne0inhk

n8n部署安装(docker)、支持Code in Python (Native)节点

n8n部署安装(docker)、支持Code in Python (Native)节点 前提条件: docker、docker compose已部署安装,可参考docker和docker compose部署安装 文件目录结构: n8n/ ├─ docker-compose.yaml ├─ .env ├─ n8n-task-runners.json 一、部署安装 1.镜像拉取 docker pull docker.n8n.io/n8nio/n8n #如果下载不下来,可用国内镜像,但是这个镜像名字要和国内镜像网址上的名字一致,比如国内轩辕镜像用的是 docker pull n8nio/n8n 2.创建docker-compose.yaml配置文件 version:'3'services:n8n:image: n8nio/

By Ne0inhk
Python——50道面试题,面试巩固必看,建议收藏!

Python——50道面试题,面试巩固必看,建议收藏!

Python大礼包:《2025年最新Python全套学习资料包】免费领取 题目001: 在Python中如何实现单例模式。 点评:单例模式是指让一个类只能创建出唯一的实例,这个题目在面试中出现的频率极高,因为它考察的不仅仅是单例模式,更是对Python语言到底掌握到何种程度,建议大家用装饰器和元类这两种方式来实现单例模式,因为这两种方式的通用性最强,而且也可以顺便展示自己对装饰器和元类中两个关键知识点的理解。 方法一:使用装饰器实现单例模式。 from functools import wraps def singleton(cls): """单例类装饰器""" instances = {} @wraps(cls) def wrapper(*args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return

By Ne0inhk