Python内存泄漏排查实战指南
如何排查Python程序中的内存泄漏?列出常用工具和方法:gc模块(get_objects/get_referrers/set_debug)、objgraph、tracemalloc、pympler/memory_profiler。如何对比堆快照(heap snapshot)定位泄漏对象?典型的泄漏模式有哪些(循环引用+del、全局缓存、闭包、C扩展泄漏)?
回答
我还是少年
排查工具:
gc模块(内置):
import gc
gc.set_debug(gc.DEBUG_LEAK | gc.DEBUG_STATS)
print(len(gc.get_objects())) # 跟踪对象数量
tracemalloc(Python 3.4+):跟踪内存分配
import tracemalloc
tracemalloc.start()
# 运行代码
snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('lineno')
for stat in top_stats[:10]:
print(stat)
objgraph:生成对象引用图
objgraph.show_refs(my_obj, filename='refs.png')
pympler:from pympler import muppy, summary; summary.print_(summary.summarize(muppy.get_objects()))
典型泄漏模式:
- 循环引用+
__del__(Python 3.4前):可回收但释放顺序不确定,GC无法回收 - 全局缓存/集未清理:
_cache = {}无限增长 - 闭包引用:回调节点持有大对象引用
- C扩展泄漏:malloc/free不匹配
- 线程泄露:未daemon的线程持有大对象
定位方法:
- 在关键点调用
gc.collect()后对比对象计数 tracemalloc对比两次快照的增量objgraph.show_growth()展示新增对象类型