本文目录导读:
- 案例一:
SyntaxError— 漏写括号或冒号 - 案例二:
NameError— 变量未定义 - 案例三:
TypeError— 类型不匹配 - 案例四:
IndexError/KeyError— 索引或键不存在 - 案例五:
AttributeError— 对象没有该属性/方法 - 案例六:
ImportError/ModuleNotFoundError— 模块找不到 - 案例七:
ValueError— 传入了正确类型但不合法的值 - 案例八:
IndentationError— 缩进错误 - 案例九:
RecursionError— 递归过深或无限递归 - 案例十:
StopIteration/GeneratorExit— 生成器/迭代器异常 - 高级案例:线程/进程间共享数据导致的
RuntimeError或PickleError - 通用排查思路总结
Python错误排查是开发中必不可少的技能,掌握常见的错误类型和排查方法能大幅提升效率,以下是几个经典的错误排查案例,涵盖语法、运行时、逻辑、环境以及并发等常见场景。
SyntaxError — 漏写括号或冒号
场景: 在 print 或函数定义时漏了括号,或者 if/for 漏了冒号。
错误示例:
print("hello" # 缺少右括号
输出:
SyntaxError: unexpected EOF while parsing
排查技巧:
- 检查代码行号,通常错误发生在上一行或当前行。
- 使用 IDE(如 PyCharm、VS Code)的语法高亮,括号/冒号缺失会直接标红。
NameError — 变量未定义
场景: 拼写错误或在作用域外访问变量。
错误示例:
name = "Alice" print(nam) # 拼写错误
输出:
NameError: name 'nam' is not defined
排查技巧:
- 直接搜索代码中变量名是否有拼写错误。
- 使用
print(dir())查看当前作用域所有可用变量。 - 如果是函数内变量未定义,检查是否忘记
global声明。
TypeError — 类型不匹配
场景: 对不可迭代对象进行迭代,或字符串与整数拼接。
错误示例:
num = 123
for i in num: # int 不可迭代
print(i)
输出:
TypeError: 'int' object is not iterable
排查技巧:
- 检查变量类型:用
type()输出当前变量类型。 - 在不确定时使用
isinstance()进行类型检查,或使用try/except捕获异常后打印类型。
IndexError / KeyError — 索引或键不存在
场景: 列表越界,字典键不存在。
错误示例:
my_list = [1, 2, 3] print(my_list[5]) # 索引越界
输出:
IndexError: list index out of range
排查技巧:
- 检查列表长度:
len(my_list) - 检查字典时,先使用
if key in my_dict:或.get(key, default)方法。 - 常见陷阱:循环中动态删除列表元素导致索引错乱(推荐用列表推导式或倒序遍历)。
AttributeError — 对象没有该属性/方法
场景: None 对象上调用方法,或误用模块名。
错误示例:
text = None print(text.upper()) # None 没有 upper
输出:
AttributeError: 'NoneType' object has no attribute 'upper'
排查技巧:
- 检查变量是否被赋值为
None(常见于函数未返回任何值)。 - 用
hasattr(obj, 'attr_name')提前判断。 - 对于导入模块,检查是否拼写错误:
import numpy却写numpy.array。
ImportError / ModuleNotFoundError — 模块找不到
场景: 未安装库、文件名冲突、路径问题。
错误示例:
import pandas # 未安装
输出:
ModuleNotFoundError: No module named 'pandas'
排查技巧:
- 确认安装:
pip list | grep pandas或conda list pandas。 - 检查是否存在自定义文件与标准库重名(比如自己写了
random.py,导致无法导入标准库random)。 - 如果包在子目录中,确保有
__init__.py文件(Python 2)或使用相对导入。
ValueError — 传入了正确类型但不合法的值
场景: 字符串转整数时包含字母、数学函数域外。
错误示例:
int("abc") # 无法转换
输出:
ValueError: invalid literal for int() with base 10: 'abc'
排查技巧:
- 检查输入数据的格式,使用正则或异常捕获来预处理。
- 数学运算如
math.sqrt(-1)会引发ValueError(复数用cmath.sqrt)。
IndentationError — 缩进错误
场景: 混用 Tab 和空格,或忘记缩进。
错误示例:
def hello():
print("world") # 未缩进
输出:
IndentationError: expected an indented block
排查技巧:
- 统一使用空格(推荐 4 个空格),在 IDE 中开启“显示空白字符”功能。
- 确保代码块对齐一致(同一级缩进必须相同)。
RecursionError — 递归过深或无限递归
场景: 递归函数缺少终止条件。
错误示例:
def foo():
return foo() # 无限循环
foo()
输出:
RecursionError: maximum recursion depth exceeded
排查技巧:
- 检查递归终止条件是否被达到。
- 增大递归深度限制(
sys.setrecursionlimit(10000))通常只是临时方案,应优先优化算法。
StopIteration / GeneratorExit — 生成器/迭代器异常
场景: 手动调用 next() 超过迭代器范围。
错误示例:
gen = (x for x in range(3)) next(gen); next(gen); next(gen); next(gen) # 第四次要停止
输出:
StopIteration
排查技巧:
- 使用
for循环代替手动next(),会自动处理停止。 - 如果需要手动控制,用
try/except StopIteration捕获并处理。
高级案例:线程/进程间共享数据导致的 RuntimeError 或 PickleError
场景: 多线程中直接修改 GUI 元素,或尝试将不可 pickle 的对象传入 multiprocessing。
错误示例:
import multiprocessing
import threading
def worker():
print(threading.current_thread().name)
if __name__ == "__main__":
p = multiprocessing.Process(target=worker)
p.start() # 正常,但如果 target 是一个 lambda 或嵌套函数,可能 pickle 失败
worker 是在另一个线程中定义的 lambda,会报:
AttributeError: Can't pickle local object 'f.<locals>.<lambda>'
排查技巧:
- 对于
multiprocessing,确保所有传递的函数/数据都是可 pickled 的(顶层函数、类、内置类型)。 - 多线程中访问共享变量时,使用
threading.Lock或queue.Queue。
通用排查思路总结
- 复现最小化:注释掉部分代码,找出引发错误的最简输入。
- 打印调试:在可疑位置加
print()输出变量类型、值、长度等。 - 使用
traceback:import traceback try: ... except Exception: traceback.print_exc() - 检查环境差异:本地 vs 服务器、Python 版本、第三方库版本(
pip freeze)。 - 利用静态分析工具:
pylint、mypy检查类型问题,flake8检查格式。
如果你有具体的代码片段报错,可以贴出来,我可以帮你一步步定位原因。
标签: Python错误排查