本文目录导读:
我来给你演示几个Python断点调试的实战案例,从基础到进阶:
基础断点调试案例
# debug_demo1.py
def calculate_average(numbers):
"""计算平均值"""
total = 0
count = 0
for num in numbers:
total += num
count += 1
print(f"当前总数: {total}, 当前计数: {count}") # 这里可以设置断点
average = total / count
return average
def complex_calculation(x, y):
"""复杂计算"""
result1 = x ** 2 + y ** 2
result2 = (x + y) * (x - y)
final_result = result1 / result2 if result2 != 0 else 0
# 这里可以设置条件断点,比如当 final_result > 10 时暂停
if final_result > 10:
print("结果大于10!")
return final_result
# 主程序
if __name__ == "__main__":
# 测试数据
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 设置断点观察执行流程
avg = calculate_average(data)
print(f"平均值: {avg}")
# 复杂计算
result = complex_calculation(5, 3)
print(f"复杂计算结果: {result}")
使用pdb进行调试
# pdb_debug.py
import pdb
def factorial(n):
"""计算阶乘"""
if n < 0:
return None
if n == 0 or n == 1:
return 1
result = 1
for i in range(1, n + 1):
result *= i
# 设置断点,观察中间值
# pdb.set_trace() # 取消注释启用pdb
return result
def process_data(items):
"""处理数据列表"""
processed = []
for index, item in enumerate(items):
try:
# 模拟可能出错的场景
value = float(item)
if value > 100:
pdb.set_trace() # 当值大于100时进入调试模式
processed.append({
'index': index,
'original': item,
'value': value,
'squared': value ** 2
})
except (ValueError, TypeError) as e:
print(f"处理项 {item} 时出错: {e}")
continue
return processed
# 使用示例
if __name__ == "__main__":
# 测试阶乘
print(f"5! = {factorial(5)}") # 可以在此设置断点
# 测试数据处理
mixed_data = ['10', '20', 'abc', '150', '30.5', '-5']
results = process_data(mixed_data)
print("处理结果:")
for r in results:
print(f"索引 {r['index']}: 原始值={r['original']}, 值={r['value']}, 平方={r['squared']}")
使用IPython的%debug魔法命令
# ipython_debug_demo.py
def buggy_function():
"""含有bug的函数示例"""
data = [1, 2, 3, 4, 5]
result = []
for i in range(len(data) + 1): # 故意越界
try:
value = data[i] * 2
result.append(value / (i - 2)) # 当i=2时会除以0
except Exception as e:
print(f"错误: {e}")
# 这里可以插入pdb.set_trace()进行调试
raise
return result
def analyze_data(data):
"""数据分析函数"""
if len(data) == 0:
return None
total = sum(data)
mean = total / len(data)
# 计算方差
variance = sum((x - mean) ** 2 for x in data) / len(data)
std_dev = variance ** 0.5
# 计算异常值
threshold = 2 * std_dev
outliers = [x for x in data if abs(x - mean) > threshold]
return {
'mean': mean,
'std_dev': std_dev,
'outliers': outliers,
'data_range': (min(data), max(data))
}
# 使用IPython的%debug调试
if __name__ == "__main__":
# 在IPython环境中可以这样使用:
# %run ipython_debug_demo.py
# 遇到错误后输入 %debug 进入调试模式
try:
# 测试分析函数
test_data = [10, 12, 11, 13, 9, 100, 11, 12, 10, 11]
analysis = analyze_data(test_data)
print(f"分析结果: {analysis}")
# 触发bug
result = buggy_function()
print(result)
except Exception as e:
print(f"发生错误: {e}")
print("在IPython中可输入 %debug 进行调试")
使用VSCode/PyCharm图形化断点
# ide_debug_demo.py
class DataProcessor:
"""数据处理类,适合IDE断点调试"""
def __init__(self, data):
self.data = data
self.processed_data = []
self.statistics = {}
def validate_data(self):
"""数据验证"""
valid_data = []
for item in self.data:
try:
if isinstance(item, (int, float)):
if 0 <= item <= 100: # 可以在这里设置条件断点
valid_data.append(item)
else:
print(f"数据 {item} 超出范围")
else:
print(f"数据 {item} 类型错误")
except Exception as e:
print(f"验证错误: {e}")
return valid_data
def transform_data(self, data):
"""数据转换"""
transformed = []
for value in data:
# 可以在这里设置条件断点,value > 50
new_value = value * 1.5 + 10
transformed.append(new_value)
return transformed
def analyze_data(self, data):
"""数据分析"""
if not data:
return {}
analysis = {
'count': len(data),
'sum': sum(data),
'mean': sum(data) / len(data) if data else 0,
'max': max(data),
'min': min(data)
}
# 计算百分位数
sorted_data = sorted(data)
n = len(sorted_data)
analysis['p50'] = sorted_data[n // 2] # 中位数
analysis['p90'] = sorted_data[int(n * 0.9)] # 90百分位
return analysis
def process(self):
"""主处理流程"""
print("开始数据处理...")
# 在IDE中可以在此处设置断点,逐行查看执行过程
valid_data = self.validate_data()
print(f"验证后的数据: {valid_data}")
transformed_data = self.transform_data(valid_data)
print(f"转换后的数据: {transformed_data}")
analysis = self.analyze_data(transformed_data)
print(f"分析结果: {analysis}")
self.processed_data = transformed_data
self.statistics = analysis
return transformed_data, analysis
# 调试主程序
if __name__ == "__main__":
# 创建测试数据
test_data = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, -5, 105, 'abc']
# 实例化处理器
processor = DataProcessor(test_data)
# 在IDE中在此处设置断点,逐行调试
processed_data, stats = processor.process()
print("\n最终结果:")
print(f"处理后的数据: {processed_data}")
print(f"统计数据: {stats}")
高级调试技巧实例
# advanced_debug.py
import logging
from functools import wraps
# 设置日志记录
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s')
def debug_decorator(func):
"""调试装饰器"""
@wraps(func)
def wrapper(*args, **kwargs):
logging.debug(f"调用函数: {func.__name__}")
logging.debug(f"位置参数: {args}")
logging.debug(f"关键字参数: {kwargs}")
try:
result = func(*args, **kwargs)
logging.debug(f"函数返回: {result}")
return result
except Exception as e:
logging.error(f"函数出错: {e}")
raise
return wrapper
@debug_decorator
def complex_algorithm(data, threshold=0.5):
"""复杂算法示例"""
result = []
for i, value in enumerate(data):
# 可以在这里设置条件断点
if value > threshold:
transformed = value * (i + 1) ** 2
result.append({
'index': i,
'original': value,
'transformed': transformed,
'threshold': threshold
})
# 当transformed超过一定值时,记录日志
if transformed > 100:
logging.warning(f"值过大: index={i}, transformed={transformed}")
return result
def recursive_debug(n, depth=0):
"""递归函数调试示例"""
indent = " " * depth
logging.debug(f"{indent}进入递归: n={n}, depth={depth}")
# 基本条件
if n <= 1:
logging.debug(f"{indent}基本条件满足,返回 1")
return 1
# 递归调用
result = n * recursive_debug(n - 1, depth + 1)
logging.debug(f"{indent}递归返回: n={n}, result={result}")
return result
# 主程序
if __name__ == "__main__":
# 测试复杂算法
test_data = [0.1, 0.6, 0.3, 0.8, 0.2, 0.9]
results = complex_algorithm(test_data, 0.5)
print("\n算法结果:")
for r in results:
print(f"索引 {r['index']}: 原始值={r['original']}, "
f"转换值={r['transformed']}, 阈值={r['threshold']}")
print("\n" + "="*50)
# 测试递归函数
n = 5
factorial = recursive_debug(n)
print(f"\n{n}! = {factorial}")
调试实战技巧
# debug_tips.py
def debug_tips_demo():
"""断点调试实用技巧"""
# 1. 条件断点示例
numbers = list(range(20))
for i, num in enumerate(numbers):
# 仅在 num % 3 == 0 时暂停
if num % 3 == 0: # 在IDE中对此行设置条件断点: num % 3 == 0
print(f"找到3的倍数: {num}")
# 2. 观察点(Watch)示例
data_stream = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
running_total = 0
for value in data_stream:
running_total += value
# 观察 running_total 的变化
# 当 running_total > 30 时设置条件断点
if running_total > 30: # 条件断点位置
print(f"总和超过30: {running_total}")
# 3. 多线程调试
import threading
import time
def worker(name, delay):
for i in range(5):
time.sleep(delay)
print(f"{name}: 第{i+1}次执行")
# 在此设置断点观察线程执行顺序
threads = []
for i in range(3):
t = threading.Thread(target=worker, args=(f"线程{i}", 0.1 * (i+1)))
threads.append(t)
t.start()
for t in threads:
t.join()
# 4. 异常断点
def risky_operation():
"""可能抛出多种异常的操作"""
try:
# 故意制造不同类型错误
x = 1 / 0 # ZeroDivisionError
except ZeroDivisionError:
print("除以零错误")
try:
y = int("abc") # ValueError
except ValueError:
print("类型转换错误")
try:
z = [1, 2, 3][10] # IndexError
except IndexError:
print("索引越界错误")
# 运行演示
if __name__ == "__main__":
print("=== 断点调试技巧演示 ===")
debug_tips_demo()
print("\n=== 危险操作演示 ===")
risky_operation()
使用建议
-
选择合适的调试工具:
- 简单调试:使用
print()语句 - 复杂调试:使用 IDE 图形化断点(VSCode/PyCharm)
- 高级调试:使用 pdb/ipdb 命令行工具
- 简单调试:使用
-
断点类型:
- 普通断点:在任何行设置
- 条件断点:满足特定条件时才暂停
- 异常断点:当抛出异常时暂停
- 日志断点:记录信息但不暂停
-
调试技巧:
- 使用 Watch 观察特定变量
- 使用 Call Stack 查看函数调用链
- 使用 Step Over/Into/Out 控制执行流程
- 使用 Evaluate Expression 执行临时代码
这些案例涵盖了Python断点调试的主要场景和技巧,你可以根据自己的需要选择合适的方式进行调试。
标签: 案例实操