Python 3.x 在Python中如何进行垃圾收集?

Python 3.x 在Python中如何进行垃圾收集?,python-3.x,garbage-collection,Python 3.x,Garbage Collection,在Python中如何进行垃圾收集。有人说这是自动发生的。但是正确的过程是什么呢?Python内存管理简介 Python的内存分配和释放方法是自动的。当用户使用诸如C或C++之类的语言的动态内存分配时,用户不必预先分配或释放内存。Python使用两种策略进行内存分配、引用计数和垃圾收集 在Python版本2.0之前,Python解释器仅使用引用计数进行内存管理。引用计数通过计算对象被系统中其他对象引用的次数来工作。删除对对象的引用时,对象的引用计数将递减。当引用计数变为零时,对象被解除分配 引用计

在Python中如何进行垃圾收集。有人说这是自动发生的。但是正确的过程是什么呢?

Python内存管理简介

Python的内存分配和释放方法是自动的。当用户使用诸如C或C++之类的语言的动态内存分配时,用户不必预先分配或释放内存。Python使用两种策略进行内存分配、引用计数和垃圾收集

在Python版本2.0之前,Python解释器仅使用引用计数进行内存管理。引用计数通过计算对象被系统中其他对象引用的次数来工作。删除对对象的引用时,对象的引用计数将递减。当引用计数变为零时,对象被解除分配

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

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

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

循环的自动垃圾收集

因为引用周期需要计算工作才能发现,所以垃圾收集必须是一个计划的活动。Python根据对象分配和对象释放的阈值安排垃圾收集。当分配数减去释放数大于阈值数时,将运行垃圾回收器。通过加载gc模块并请求垃圾收集阈值,可以检查新对象(Python中称为第0代对象的对象)的阈值:

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

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

如果Python设备内存不足,则不会运行自动垃圾收集;相反,您的应用程序将抛出异常,这些异常必须得到处理,否则您的应用程序将崩溃。自动垃圾收集对自由对象的数量,而不是它们的大小有很大的影响,这一事实加剧了这种情况。因此,代码中释放大块内存的任何部分都是运行手动垃圾收集的良好候选

手动垃圾收集

对于某些程序,尤其是长时间运行的服务器应用程序或在Digi设备上运行的嵌入式应用程序,自动垃圾收集可能不够。尽管一个应用程序应该尽可能地不受引用循环的影响,但最好有一个策略来处理它们。在程序执行的适当时候手动调用垃圾收集器是处理引用周期占用的内存的一个好主意

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

import gc
gc.collect()
import gc
collected = gc.collect()
print "Garbage collector: collected %d objects." % (collected)
collect()返回它收集和释放的对象数。您可以按以下方式打印此信息:

import gc
gc.collect()
import gc
collected = gc.collect()
print "Garbage collector: collected %d objects." % (collected)
如果我们创建几个循环,我们可以看到手动收集工作:

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)
通常,有两种推荐的执行手动垃圾收集的策略:基于时间的垃圾收集和基于事件的垃圾收集。基于时间的垃圾收集很简单:在固定的时间间隔调用垃圾收集器。基于事件的垃圾回收在事件上调用垃圾回收器。例如,当用户断开与应用程序的连接或已知应用程序进入空闲状态时

参考资料:


了解python垃圾收集的内部结构,以及Instagram工程师如何通过调整垃圾收集实现10%的性能改进