17370845950

Python垃圾回收机制教程_gc模块工作原理
Python垃圾回收以引用计数为主,对象refcount为0时立即释放;循环引用由gc模块用分代收集(三代)清理;可手动控制gc启停、强制回收、调参及调试。

Python的垃圾回收主要靠引用计数

Python默认使用引用计数作为最核心的内存管理机制。每个对象内部都维护一个refcount,记录当前有多少变量或数据结构正指向它。当这个数值降为0,对象立即被释放,内存立刻归还给系统。这是最及时、最确定的回收方式。

例如:

a = [1, 2, 3] → 列表对象 refcount = 1
b = a → 同一列表,refcount 变为 2
del a → refcount 减为 1
del b → refcount 变为 0 → 对象被销毁

循环引用靠gc模块来清理

引用计数无法处理循环引用:比如A持有B的引用,B也持有A的引用,但外部已无变量指向它们。此时两个对象 refcount 都不为0,却成了“内存孤岛”。Python用gc模块周期性地扫描并识别这类不可达的循环结构。

gc模块基于三色标记-清除算法(实际是简化版的分代收集)工作:

  • 把所有对象按“存活时间”分为三代(0/1/2),新对象在第0代
  • 第0代满阈值时触发收集,存活对象升级到第1代;第1代满阈值后,连同第0代一起收集,存活者升入第2代
  • 越老的对象越少被扫描,提升效率

手动控制gc行为的常用方法

虽然gc默认开启且自动运行,但你可以在需要时干预:

  • gc.enable() / gc.disable():启用或暂停自动回收(调试或性能敏感场景可用)
  • gc.collect([generation]):强制执行一次回收,可指定代(如gc.collect(0)只清理第0代)
  • gc.get_count():返回当前三代的计数器值,如(712, 9, 0)表示第0代已触发712次收集
  • gc.set_threshold(x, y, z):调整各代触发阈值,默认是(700, 10, 10)

对象如何参与gc:__del__与gc.garbage

如果自定义类定义了__del__方法,该对象会被gc特殊对待——它不会被直接清除,而是先放入gc.garbage列表(需手动处理),防止<__del__>执行期间引发异常导致状态不一致。

注意:__del__不是析构函数,不保证何时调用,也不推荐依赖它做关键资源释放(应优先用with语句或显式close())。

若发现内存泄漏怀疑有未清理的循环引用,可临时启用:

gc.set_debug(gc.DEBUG_SAVEALL) → 所有无法回收的对象会留在gc.garbage中供检查