Python 中的垃圾回收是如何进行的?

DEB*_*KAR -2 garbage-collection python-3.x

Python 中如何进行垃圾收集。有人说这是自动发生的。但其正确的流程是怎样的呢?

Amm*_*ema 7

Python内存管理简介

Python的内存分配和释放方法是自动的。用户不必像在 C 或 C++ 等语言中使用动态内存分配时那样手动预分配或取消分配内存。Python 使用两种内存分配策略、引用计数和垃圾回收策略。

在Python 2.0版本之前,Python解释器仅使用引用计数来进行内存管理。引用计数的工作原理是计算一个对象被系统中其他对象引用的次数。当删除对对象的引用时,对象的引用计数就会减少。当引用计数变为零时,对象将被释放。

引用计数非常有效,但它确实有一些警告。其中一个警告是它无法处理引用循环。引用循环是指无法到达对象但其引用计数仍大于零的情况。创建引用循环的最简单方法是创建一个引用自身的对象,如下例所示:

def make_cycle():
    1 = [ ]
    1.append(l)

make_cycle()
Run Code Online (Sandbox Code Playgroud)

因为 make_cycle() 创建了一个引用自身的对象 1,所以当函数返回时,对象 1 不会自动被释放。这将导致 1 正在使用的内存被保留,直到调用 Python 垃圾收集器。

周期自动垃圾收集

由于引用循环需要计算工作才能发现,因此垃圾收集必须是计划的活动。Python 根据对象分配和对象释放的阈值来安排垃圾收集。当分配数量减去释放数量大于阈值数量时,垃圾收集器就会运行。可以通过加载 gc 模块并询问垃圾收集阈值来检查新对象(Python 中的对象称为第 0 代对象)的阈值:

import gc
print "Garbage collection thresholds: %r" % gc.get_threshold()

Garbage collection thresholds: (700, 10, 10)
Run Code Online (Sandbox Code Playgroud)

在这里我们可以看到上述系统的默认阈值是 700。这意味着当分配数量与释放数量大于 700 时,自动垃圾收集器将运行。

如果你的 Python 设备内存不足,自动垃圾收集将不会运行;相反,您的应用程序将抛出异​​常,必须处理该异常,否则您的应用程序将崩溃。由于自动垃圾收集高度重视空闲对象的数量,而不是它们的大小,这一事实加剧了这一情况。因此,释放大内存块的代码的任何部分都是运行手动垃圾收集的良好候选者。

手动垃圾收集

对于某些程序,尤其是长时间运行的服务器应用程序或在 Digi 设备上运行的嵌入式应用程序,自动垃圾收集可能还不够。尽管应将应用程序编写为尽可能没有引用循环,但最好制定一个处理它们的策略。在程序执行的适当时间手动调用垃圾收集器可能是处理引用周期消耗的内存的好主意。

可以通过以下方式手动调用垃圾收集:

import gc
gc.collect()
Run Code Online (Sandbox Code Playgroud)

gc.collect() 返回它已收集和释放的对象数量。您可以通过以下方式打印此信息:

import gc
collected = gc.collect()
print "Garbage collector: collected %d objects." % (collected)
Run Code Online (Sandbox Code Playgroud)

如果我们创建几个周期,我们可以看到手动收集工作:

import sys, gc

def make_cycle():
    1 = { }
    1[0] = 1

def main():
collected = gc.collect()
print "Garbage collector: collected %d objects." % (collected)
print "Creating cycles..."
for i in range(10):
    make_cycle()
    collected = gc.collect()
    print "Garbage collector: collected %d objects." % (collected)

if __name__ == "__main__":
ret = main()
sys.exit(ret)
Run Code Online (Sandbox Code Playgroud)

一般来说,有两种执行手动垃圾收集的推荐策略:基于时间的垃圾收集和基于事件的垃圾收集。基于时间的垃圾收集很简单:垃圾收集器以固定的时间间隔被调用。基于事件的垃圾收集针对事件调用垃圾收集器。例如,当用户与应用程序断开连接时或当已知应用程序进入空闲状态时。

参考:

Python 垃圾收集