Skip to content

调试技巧

快速定位和解决问题


调试的层次

  1. Print 调试(最简单)
  2. 断言(Assert)
  3. 日志(Logging)
  4. 调试器(Debugger)

基本用法

python
def calculate_tax(income, rate):
    print(f"Debug: income={income}, rate={rate}")  # 调试输出
    tax = income * rate
    print(f"Debug: tax={tax}")
    return tax

result = calculate_tax(100000, 0.25)

变量检查

python
data = [1, 2, 3, 4, 5]
print(f"类型: {type(data)}")
print(f"长度: {len(data)}")
print(f"内容: {data}")

断言(Assert)

python
def calculate_mean(data):
    assert len(data) > 0, "数据不能为空"
    assert all(isinstance(x, (int, float)) for x in data), "必须是数字"

    return sum(data) / len(data)

#  正常
result = calculate_mean([1, 2, 3])

#  触发断言
result = calculate_mean([])  # AssertionError: 数据不能为空

日志(Logging)

python
import logging

# 配置日志
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(levelname)s - %(message)s',
    filename='analysis.log'
)

# 使用日志
logging.debug("开始处理数据")
logging.info("加载了 1000 行数据")
logging.warning("发现 15 个缺失值")
logging.error("文件读取失败")
logging.critical("系统崩溃")

日志级别

  • DEBUG:详细信息
  • INFO:一般信息
  • WARNING:警告
  • ERROR:错误
  • CRITICAL:严重错误

实战技巧

技巧 1:条件断点

python
for i, resp in enumerate(respondents):
    if resp['id'] == 1001:  # 只调试特定数据
        print(f"调试 ID 1001: {resp}")

技巧 2:检查数据类型

python
def process_income(income):
    print(f"income 类型: {type(income)}")
    print(f"income 值: {repr(income)}")

    if not isinstance(income, (int, float)):
        raise TypeError(f"期望数字,得到 {type(income)}")

技巧 3:使用 pdb(Python Debugger)

python
import pdb

def analyze_data(df):
    print("开始分析")
    pdb.set_trace()  # 程序会在这里暂停
    result = df.mean()
    return result

# 调试命令:
# n (next): 下一行
# s (step): 进入函数
# c (continue): 继续执行
# p variable: 打印变量
# q (quit): 退出

常见问题调试

问题 1:数据类型错误

python
#  隐藏的类型问题
ages = ['25', '30', '35']  # 字符串列表
mean = sum(ages) / len(ages)  # TypeError

#  调试
print(f"ages 类型: {type(ages)}")
print(f"第一个元素类型: {type(ages[0])}")

# 修复
ages = [int(x) for x in ages]

问题 2:数据框列名错误

python
import pandas as pd

df = pd.DataFrame({'age': [25, 30], 'income': [50000, 75000]})

#  KeyError
mean_incom = df['incom'].mean()  # 拼写错误

#  调试
print("可用列:", df.columns.tolist())
print("列名类型:", [type(col) for col in df.columns])

问题 3:循环中的索引问题

python
data = [10, 20, 30]

#  IndexError
for i in range(len(data) + 1):  # 范围错误
    print(data[i])

#  调试
print(f"数据长度: {len(data)}")
print(f"循环范围: {list(range(len(data) + 1))}")

调试清单

数据问题

  • [ ] 检查数据类型
  • [ ] 检查数据长度/形状
  • [ ] 检查缺失值
  • [ ] 检查异常值

逻辑问题

  • [ ] 打印中间结果
  • [ ] 检查条件判断
  • [ ] 验证循环范围
  • [ ] 确认函数参数

性能问题

  • [ ] 使用时间测量
  • [ ] 检查算法复杂度
  • [ ] 查找重复计算

实用调试模板

python
import logging
import traceback

# 配置
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

def safe_process(data):
    """带完整调试的处理函数"""
    try:
        # 输入验证
        logging.debug(f"输入数据类型: {type(data)}")
        logging.debug(f"输入数据长度: {len(data)}")

        # 主要处理
        result = process_logic(data)

        # 输出验证
        logging.debug(f"输出结果: {result}")
        return result

    except Exception as e:
        logging.error(f"处理失败: {e}")
        logging.error(traceback.format_exc())
        return None

总结

调试顺序

  1. 读错误信息(最重要!)
  2. 添加 print 语句
  3. 检查数据类型和值
  4. 使用 logging
  5. 使用调试器(pdb)

Module 8 完成!

下一个模块是核心重点:Module 9 常用库(NumPy/Pandas/可视化等)

准备好了吗?

基于 MIT 许可证发布。内容版权归作者所有。