故事:
在Python的内存管理Nina Zakharenko's PyCon talk期间,她解释了分代垃圾收集在Python中的工作方式,并注意到:
Python维护一个在程序运行时创建的每个对象的列表。实际上,它使3:
generation 0
generation 1
generation 2
问题:
为了更好地理解Python中的内存管理以及调试内存泄漏的目的,如何在程序运行期间观察/观察在所有3代列表中添加和删除的对象 ?
我查看了gc
module,但没有找到相关方法来获取当前的生成列表值。
答案 0 :(得分:3)
正如我们在评论中讨论的那样,我认为有一种方法可以直接从python访问生成列表,你可以设置一些调试标志,在python2中你可以使用以下内容来报告可以或者无法收集:
import gc
gc.set_debug(gc.DEBUG_UNCOLLECTABLE | gc.DEBUG_COLLECTABLE | gc.DEBUG_OBJECTS )
在python3中,使用以下内容将为您提供有关可收集和不可收集对象的一些生成输出和信息:
import gc
gc.set_debug(gc.DEBUG_UNCOLLECTABLE | gc.DEBUG_COLLECTABLE | gc.DEBUG_STATS)
输出如下:
gc: collecting generation 2...
gc: objects in each generation: 265 4454 0
gc: collectable <function 0x7fad67f77b70>
gc: collectable <tuple 0x7fad67f6f710>
gc: collectable <dict 0x7fad67f0e3c8>
gc: collectable <type 0x285db78>
gc: collectable <getset_descriptor 0x7fad67f095e8>
gc: collectable <getset_descriptor 0x7fad67f09630>
gc: collectable <tuple 0x7fad67f05b88>
gc: done, 7 unreachable, 0 uncollectable, 0.0028s elapsed.
gc: collecting generation 2...
对于设置时gc.DEBUG_SAVEALL
的泄漏,找到的所有无法访问的对象都将附加到垃圾而不是被释放。这对于调试泄漏程序非常有用:
import gc
gc.set_debug(gc.DEBUG_SAVEALL)
在python3中,你还可以附加一个在gc启动和结束时运行的回调,一个简单的例子:
def f(phase, info):
if phase == "start":
print("starting garbage collection....")
else:
print("Finished garbage collection.... \n{}".format("".join(["{}: {}\n".format(*tup) for tup in info.items()])))
print("Unreachable objects: \n{}".format(
"\n".join([str(garb) for garb in gc.garbage])))
print()
gc.callbacks.append(f)
将gc.DEBUG_SAVEALL
与该功能结合使用会向您显示任何无法访问的对象,与设置DEBUG_COLLECTABLE
或DEBUG_LEAK差别不大,只是添加callback的一个示例。