本文目录导读:
我来详细介绍如何编写Python调试案例,包含常见的错误类型和调试技巧。
基础调试案例
案例1:语法错误调试
# error_example1_syntax.py
def calculate_average(numbers):
total = 0
for num in numbers
total += num # 语法错误:缺少冒号
return total / len(numbers)
# 正确的版本
def calculate_average_fixed(numbers):
total = 0
for num in numbers: # 添加冒号
total += num
return total / len(numbers)
案例2:类型错误调试
# error_example2_type.py
def process_data(data):
# 类型错误示例
result = data + 10 # 如果data是字符串会出错
return result
# 调试过程
def debug_type_error():
test_cases = [10, "20", [1,2,3], None]
for item in test_cases:
try:
print(f"处理 {item}: ", end="")
result = process_data(item)
print(f"成功: {result}")
except Exception as e:
print(f"错误: {type(e).__name__}: {e}")
# 改进版本:添加类型检查
def process_data_safe(data):
if not isinstance(data, (int, float)):
raise ValueError(f"期望数字类型,得到 {type(data).__name__}")
return data + 10
逻辑错误调试案例
案例3:循环逻辑错误
# error_example3_logic.py
def find_first_duplicate(items):
"""找到列表中第一个重复的元素"""
seen = []
for item in items:
if item in seen: # 逻辑错误:应该先添加再检查
return item
seen.append(item)
return None
# 调试版本
def debug_find_duplicate():
test_list = [1, 2, 3, 2, 4, 3]
print("测试列表:", test_list)
print("当前算法结果:", find_first_duplicate(test_list))
print("预期结果: 2")
# 添加调试输出
def find_first_duplicate_with_debug(items):
seen = []
for i, item in enumerate(items):
print(f"第{i}步: 检查元素 {item}, 已见列表: {seen}")
if item in seen:
print(f"找到重复: {item}")
return item
seen.append(item)
print(f"添加后: {seen}")
return None
return find_first_duplicate_with_debug(test_list)
# 修正版本
def find_first_duplicate_fixed(items):
seen = set() # 用set提高性能
for item in items:
if item in seen: # 先检查是否已存在
return item
seen.add(item) # 然后添加
return None
使用调试工具的案例
案例4:pdb调试案例
# error_example4_pdb.py
import pdb
def complex_calculation(x, y, z):
"""复杂计算函数,用于演示pdb调试"""
result = x + y
pdb.set_trace() # 设置断点
result = result * z
result = result / (x - y) # 可能除零错误
return result
# 使用pdb调试
def debug_with_pdb():
try:
result = complex_calculation(10, 5, 2)
print(f"计算成功: {result}")
except Exception as e:
print(f"计算失败: {e}")
# 更好的调试方式:使用上下文管理器
from contextlib import contextmanager
@contextmanager
def debug_context():
"""调试上下文管理器"""
print("开始调试...")
try:
yield
except Exception as e:
print(f"捕获异常: {type(e).__name__}: {e}")
print("异常追溯:")
import traceback
traceback.print_exc()
finally:
print("调试结束")
def safe_calculation(x, y, z):
with debug_context():
result = x + y
result = result * z
result = result / (x - y) # 如果x==y会出错
return result
实际应用调试案例
案例5:文件处理调试
# error_example5_file.py
import os
import json
def process_user_data(filepath):
"""处理用户数据文件"""
# 常见错误:文件不存在、JSON格式错误、编码问题
try:
with open(filepath, 'r') as file:
data = json.load(file)
# 处理数据
users = []
for user in data:
if user['age'] >= 18: # 可能缺少age字段
users.append({
'name': user['name'],
'age': user['age']
})
return users
except FileNotFoundError:
print(f"文件未找到: {filepath}")
return []
except json.JSONDecodeError as e:
print(f"JSON解析错误: {e}")
return []
except KeyError as e:
print(f"缺少必要字段: {e}")
return []
# 创建测试数据
def create_test_data():
test_data = [
{"name": "Alice", "age": 25},
{"name": "Bob", "age": 17},
{"name": "Charlie", "age": 30},
{"name": "David"} # 缺少age字段
]
with open('test_users.json', 'w') as f:
json.dump(test_data, f, indent=2)
# 创建损坏的JSON文件用于测试
with open('bad_users.json', 'w') as f:
f.write('{"name": "Broken JSON"}') # 不是列表格式
# 调试函数
def debug_file_processing():
create_test_data()
print("=== 正常文件测试 ===")
result = process_user_data('test_users.json')
print(f"结果: {result}")
print("\n=== 不存在的文件测试 ===")
result = process_user_data('nonexistent.json')
print("\n=== 损坏的JSON文件测试 ===")
result = process_user_data('bad_users.json')
# 清理测试文件
for f in ['test_users.json', 'bad_users.json']:
if os.path.exists(f):
os.remove(f)
高级调试技巧案例
案例6:日志调试
# error_example6_logging.py
import logging
import sys
# 配置日志
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('debug.log'),
logging.StreamHandler(sys.stdout)
]
)
class DataProcessor:
def __init__(self):
self.logger = logging.getLogger(__name__)
def process(self, data):
self.logger.debug(f"开始处理数据: {data}")
try:
# 模拟复杂处理
result = self._transform(data)
self.logger.info(f"数据转换成功: {result}")
validated = self._validate(result)
self.logger.debug(f"验证结果: {validated}")
return validated
except Exception as e:
self.logger.error(f"处理失败: {e}", exc_info=True)
raise
def _transform(self, data):
self.logger.info(f"转换阶段: {data}")
return [x * 2 for x in data if isinstance(x, (int, float))]
def _validate(self, data):
self.logger.info(f"验证阶段: {data}")
if not data:
self.logger.warning("空数据,返回默认值")
return [0]
return [x for x in data if x > 0]
# 使用案例
def logging_debug_example():
processor = DataProcessor()
# 正常情况
try:
result = processor.process([1, -2, 3, 0, 5])
print(f"处理结果: {result}")
except Exception as e:
print(f"错误: {e}")
# 异常情况
try:
result = processor.process([1, "string", 3])
except Exception as e:
print(f"错误: {e}")
单元测试调试案例
案例7:使用unittest调试
# error_example7_testing.py
import unittest
from unittest.mock import Mock
class Calculator:
def add(self, a, b):
return a + b
def divide(self, a, b):
if b == 0:
raise ValueError("除数不能为零")
return a / b
def complex_operation(self, a, b, c):
"""演示复杂操作的调试"""
result = self.add(a, b)
result = result * c
result = self.divide(result, b)
return result
class TestCalculator(unittest.TestCase):
def setUp(self):
"""测试前的准备工作"""
self.calc = Calculator()
print("\n初始化计算器")
def tearDown(self):
"""测试后的清理工作"""
print("测试完成")
def test_add(self):
"""测试加法"""
result = self.calc.add(3, 4)
self.assertEqual(result, 7)
# 调试输出
print(f"加法测试: 3 + 4 = {result}")
def test_divide_by_zero(self):
"""测试除零错误"""
with self.assertRaises(ValueError):
self.calc.divide(10, 0)
def test_complex_operation(self):
"""测试复杂操作"""
# 使用调试模式
result = self.calc.complex_operation(2, 3, 4)
expected = (2 + 3) * 4 / 3 # 20/3 ≈ 6.67
self.assertAlmostEqual(result, expected, places=2)
# 调试信息
print(f"复杂操作: (2+3)*4/3 = {result}")
# 运行测试
if __name__ == '__main__':
# 详细输出模式
unittest.main(verbosity=2)
性能调试案例
案例8:性能分析调试
# error_example8_performance.py
import time
from functools import wraps
def performance_monitor(func):
"""性能监控装饰器"""
@wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
end = time.perf_counter()
print(f"{func.__name__} 执行时间: {(end-start)*1000:.2f}ms")
return result
return wrapper
class PerformanceDebugger:
@performance_monitor
def slow_operation(self, n):
"""演示性能问题"""
result = []
for i in range(n):
result.append(i ** 2)
return result
@performance_monitor
def fast_operation(self, n):
"""优化版本"""
return [i ** 2 for i in range(n)]
@performance_monitor
def memory_issue(self, n):
"""内存问题演示"""
# 错误的做法:重复创建大列表
data = []
for i in range(n):
# 每次循环都创建新列表
temp = list(range(n))
data.append(temp[i])
return data
# 性能调试案例
def performance_debug_example():
debugger = PerformanceDebugger()
print("=== 性能比较 ===")
n = 10000
print("慢操作:")
result1 = debugger.slow_operation(n)
print("\n快操作:")
result2 = debugger.fast_operation(n)
print("\n内存问题:")
result3 = debugger.memory_issue(100) # 小规模测试
完整的调试工作流程
# comprehensive_debug_example.py
import traceback
import sys
def debug_workflow_example():
"""完整的调试工作流程示例"""
# 1. 设置调试模式
DEBUG_MODE = True
def debug_print(*args, **kwargs):
"""自定义调试输出"""
if DEBUG_MODE:
print("[DEBUG]", *args, **kwargs)
# 2. 复杂函数
def process_data(data, factor):
debug_print(f"输入数据: {data}, 因子: {factor}")
# 3. 分步调试
step1 = [x * factor for x in data]
debug_print(f"步骤1 (乘以{factor}): {step1}")
step2 = [x % 10 for x in step1]
debug_print(f"步骤2 (取模10): {step2}")
step3 = sum(step2) / len(step2)
debug_print(f"步骤3 (平均值): {step3}")
return step3
# 4. 测试用例
test_cases = [
([1, 2, 3], 2),
([10, 20, 30], 5),
([], 3), # 边界情况
(["a", "b"], 2) # 错误情况
]
# 5. 调试循环
for i, (data, factor) in enumerate(test_cases, 1):
print(f"\n测试用例 {i}: data={data}, factor={factor}")
try:
result = process_data(data, factor)
print(f"结果: {result}")
except Exception as e:
print(f"错误: {type(e).__name__}: {e}")
if DEBUG_MODE:
print("完整错误信息:")
traceback.print_exc()
if __name__ == "__main__":
debug_workflow_example()
调试案例使用建议
- 渐进式学习:从简单的语法错误开始,逐步到复杂的逻辑错误
- 实际场景:结合实际项目中的错误模式编写案例
- 工具使用:演示pdb、logging、unittest等调试工具
- 最佳实践:展示正确的调试习惯和错误处理方式
- 性能考虑:包含性能问题的调试案例
这些案例可以作为学习调试的教材,也可以作为开发中的调试参考模板,通过系统化的调试案例,你可以快速定位和解决Python代码中的各种问题。
标签: 案例设计