调试和性能分析
调试发现和修复错误,性能分析识别瓶颈。Python 提供丰富的工具。
print 调试
最简单的调试方法:
python
def calculate(a, b):
print(f"calculate called with a={a}, b={b}")
result = a * b + 10
print(f"result={result}")
return result
calculate(5, 3)
# 输出:
# calculate called with a=5, b=3
# result=25局限:污染代码、难以移除、不够强大。
logging 模块
结构化日志,支持级别控制:
python
import logging
# 配置
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
def process_data(data):
logging.debug(f"Processing {len(data)} items")
result = []
for item in data:
logging.debug(f"Processing item: {item}")
result.append(item * 2)
logging.info(f"Processed {len(result)} items")
return result
process_data([1, 2, 3])日志级别:
DEBUG:详细信息INFO:一般信息WARNING:警告ERROR:错误CRITICAL:严重错误
pdb 交互式调试器
Python 内置调试器:
python
import pdb
def divide(a, b):
pdb.set_trace() # 设置断点
result = a / b
return result
divide(10, 2)pdb 命令:
n(next):下一行s(step):进入函数c(continue):继续执行p variable:打印变量l(list):显示代码q(quit):退出
breakpoint()(Python 3.7+)
更简洁的断点:
python
def calculate(a, b):
result = a * b
breakpoint() # 自动进入 pdb
return result等价于 import pdb; pdb.set_trace(),但更简洁。
IDE 调试器
VS Code
- 设置断点(点击行号左侧)
- 按 F5 启动调试
- 使用工具栏控制执行
PyCharm
- 设置断点
- 右键 → Debug
- 查看变量、调用栈
优点:可视化、变量监视、条件断点。
性能分析:cProfile
分析函数调用时间:
python
import cProfile
import pstats
def slow_function():
total = 0
for i in range(1000000):
total += i
return total
def main():
result1 = slow_function()
result2 = slow_function()
return result1 + result2
# 性能分析
cProfile.run('main()', 'profile_stats')
# 查看结果
stats = pstats.Stats('profile_stats')
stats.sort_stats('cumulative')
stats.print_stats(10)输出:
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.284 0.284 <string>:1(<module>)
1 0.000 0.000 0.284 0.284 example.py:9(main)
2 0.284 0.142 0.284 0.142 example.py:3(slow_function)性能分析:timeit
精确测量小段代码:
python
import timeit
# 方法 1:列表推导
time1 = timeit.timeit('[x**2 for x in range(1000)]', number=10000)
# 方法 2:map
time2 = timeit.timeit('list(map(lambda x: x**2, range(1000)))', number=10000)
print(f"列表推导: {time1:.4f}s")
print(f"map: {time2:.4f}s")内存分析:memory_profiler
分析内存使用:
bash
pip install memory_profilerpython
# example.py
from memory_profiler import profile
@profile
def create_large_list():
large_list = [i for i in range(1000000)]
return large_list
@profile
def main():
data = create_large_list()
processed = [x * 2 for x in data]
return processed
if __name__ == '__main__':
main()运行:
bash
python -m memory_profiler example.py输出:
Line # Mem usage Increment Line Contents
================================================
3 38.1 MiB 38.1 MiB @profile
4 def create_large_list():
5 76.3 MiB 38.2 MiB large_list = [i for i in range(1000000)]
6 76.3 MiB 0.0 MiB return large_list实战案例:定位性能瓶颈
python
import cProfile
import time
def slow_computation():
"""模拟慢操作"""
time.sleep(0.1)
return sum(range(100000))
def fast_computation():
"""快速操作"""
return sum(range(100))
def main():
results = []
for _ in range(10):
results.append(slow_computation())
for _ in range(100):
results.append(fast_computation())
return results
# 性能分析
cProfile.run('main()', sort='cumulative')分析:
- 运行 cProfile
- 查看
tottime(函数自身时间) - 找到最慢的函数
- 优化瓶颈
调试技巧
1. 二分查找错误
python
def complex_function():
step1()
print("Step 1 done") # 检查点
step2()
print("Step 2 done")
step3()
print("Step 3 done")2. 断言检查
python
def process(data):
assert isinstance(data, list), "data must be a list"
assert len(data) > 0, "data cannot be empty"
# 继续处理3. 日志而非 print
python
# 不好
print("Debug info:", value)
# 好
logging.debug("Processing value: %s", value)小结
- print 简单但有限
- logging 结构化、可配置
- pdb/breakpoint() 交互式调试
- IDE 调试器 可视化、强大
- cProfile 函数级性能分析
- timeit 精确测量小段代码
- memory_profiler 内存使用分析
下一节学习 打包和发布。
参考:
练习:答案