Python 语言中,名称类型的确定、内存空间的分配与释放都是由 Python 解释器在运行时进行的。

Python 中,为了解决内存泄漏问题,采用了对象引用计数(Reference Counting),并基于引用技术实现自动垃圾回收.

Python 对于已经销毁的对象,不会自动释放其占据的内存空间,需要采用 gc(garbage collector)进行内存回收.

gc 模块

https://docs.python.org/zh-cn/3/library/gc.html

gc 模块提供可选的垃圾回收器的接口,提供的功能包括:关闭收集器、调整收集频率、设置调试选项。它同时提供对回收器找到但是无法释放的不可达对象的访问.

  • 由于 Python 使用了带有引用计数的回收器,如果确定程序不会产生循环引用,可以关闭回收器。可以通过调用 gc.disable() 关闭自动垃圾回收。
  • 若要调试一个存在内存泄漏的程序,调用 gc.set_debug(gc.DEBUG_LEAK) ;需要注意的是,它包含 gc.DEBUG_SAVEALL ,使得被垃圾回收的对象会被存放在 gc.garbage 中以待检查。

gc 模块提供的函数有:

import gc

gc.enable() #启用自动垃圾回收
gc.isenable() #判断是否启用了自动垃圾回收

gc.disable() #停用自动垃圾回收

gc.collect()
gc.collect(generation=2)
'''
gc.collect() 返回处理这些循环引用一共释放掉的对象个数

若 gc.collect() 被调用时不包含参数,则启动完全的垃圾回收。
可选的参数 generation 可以是一个整数,指明需要回收哪一代(从 0 到 2 )的垃圾。当参数 generation 无效时,会引发 ValueError 异常。返回发现的不可达对象的数目。

每当运行完整收集或最高代 (2) 收集时,为多个内置类型所维护的空闲列表会被清空。 由于特定类型特别是 float 的实现,在某些空闲列表中并非所有项都会被释放。
'''

gc.set_debug(flags) #debug 调试标识位
gc.get_debug()      #返回当前调试标识位

gc.get_objects(generation=None) #返回一个收集器所跟踪的所有对象的列表,所返回的列表除外。

gc.get_stats() #返回一个包含三个字典对象的列表,每个字典分别包含对应代的从解释器开始运行的垃圾回收统计数据。

gc.set_threshold(threshold0[, threshold1[, threshold2]])
'''
设置垃圾回收阈值(收集频率)。 将 threshold0 设为零会禁用回收。

垃圾回收器把所有对象分类为三代,其依据是对象在多少次垃圾回收后幸存。 新建对象会被放在最年轻代(第 0 代)。 如果一个对象在一次垃圾回收后幸存,它会被移入下一个较老代。 由于第 2 代是最老代,这一代的对象在一次垃圾回收后仍会保留原样。 为了确定何时要运行,垃圾回收器会跟踪自上一次回收后对象分配和释放的数量。 当分配数量减去释放数量的结果值大于 threshold0 时,垃圾回收就会开始。 初始时只有第 0 代会被检查。 如果自第 1 代被检查后第 0 代已被检查超过 threshold1 次,则第 1 也会被检查。 
'''

gc.get_threshold() #将当前回收阈值以形为 (threshold0, threshold1, threshold2) 的元组返回。
gc.get_count() #将当前回收计数以形为 (count0, count1, count2) 的元组返回。

gc.get_referrers(*objs)
'''
返回直接引用任意一个 ojbs 的对象列表。这个函数只定位支持垃圾回收的容器;引用了其它对象但不支持垃圾回收的扩展类型不会被找到。
'''
gc.get_referents(*objs) #返回被任意一个参数中的对象直接引用的对象的列表。

gc.is_tracked(obj) #当对象正在被垃圾回收器监控时返回 True ,否则返回 False。
'''
gc.is_tracked(0)   #False
gc.is_tracked("a") #False
gc.is_tracked([])  #True
gc.is_tracked({})  #False
gc.is_tracked({"a": 1})  #False
gc.is_tracked({"a": []}) #True
'''

gc.is_finalized(obj) #如果给定对象已被垃圾回收器终结则返回 True,否则返回 False.
gc.freeze()   #冻结 gc 所跟踪的所有对象
gc.unfreeze() 
gc.get_freeze_count() 
gc.callbacks() #在垃圾回收器开始前和完成后会被调用的一系列回调函数

gc.DEBUG_STATS 
#在回收完成后打印统计信息。当回收频率设置较高时,这些信息会比较有用。

gc.DEBUG_COLLECTABLE 
#当发现可回收对象时打印信息。

gc.DEBUG_UNCOLLECTABLE
#打印找到的不可回收对象的信息(指不能被回收器回收的不可达对象)

gc.DEBUG_SAVEALL
#设置后,所有回收器找到的不可达对象会被添加进 garbage 而不是直接被释放。

gc.DEBUG_LEAK
#调试内存泄漏的程序时,使回收器打印信息的调试标识位。
#(等价于 DEBUG_COLLECTABLE | DEBUG_UNCOLLECTABLE | DEBUG_SAVEALL)

示例

import gc 
import numpy as np

a = np.array([1,2,3])
del a
unreachable_objects = gc.collect()
#Number of collected and deallocated objects
print(unreachable_objects)

材料

[1] - 彻底搞懂Python 垃圾回收机制!- 2021.11.04

Last modification:April 14th, 2022 at 01:27 pm