在程序运行期间观看生成列表
故事:
在Nina Zakharenko的PyCon关于Python内存管理的谈话中,她解释了代码垃圾收集在Python中的工作方式,指出:
Python维护一个程序运行时创建的每个对象的列表。 实际上,它使3:
generation 0
generation 1
generation 2
问题是:
为了更好地理解Python中的内存管理和调试内存泄漏的目的,我如何观察/观察程序运行期间在所有3代列表中添加和删除了哪些对象?
我已经浏览了gc
模块,但还没有找到获取当前生成列表值的相关方法。
正如我们在评论中所讨论的那样,我认为没有办法直接从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没什么不同,但是添加了回调的一个示例。