Python:记录垃圾收集器
我有一个用Python写的应用程序,运行时有些卡顿。我想把垃圾回收器的事件(特别是它什么时候被调用)记录到我的日志里。这样可以吗?
谢谢。
2 个回答
1
Python(至少是CPython版本2.x)使用引用计数来实现它的垃圾回收机制(参考为什么Java和Python的垃圾回收方法不同?),所以它的工作方式和Java不太一样,不是通过“调用”来完成的。
引用计数
的意思是,每当你创建一个指向某个对象的新引用时,计数器就会加1;而每当这个引用失效(比如超出作用域、被重新赋值等),计数器就会减1。当计数器减到0时,这个对象占用的内存就会被释放。
所以Python给你问题的解决方案是重写对象的__del__
方法:
class test:
def __del__(self):
#self is about to be freed, do what ever you want
pass
编辑: 根据上面的链接,还有一个机制会定期运行:
CPython(引用计数并不是Python本身的一部分,而是其C语言实现的一部分)会通过一个单独的垃圾回收程序来处理循环引用,这个程序会定期运行……
但这个机制只在出现循环引用的情况下才会涉及。
编辑2:
正如评论中提到的,以及在这里提到的,__del__
并不是最安全的解决方案。这里有一种更好的方法来实现类似的效果:
import weakref
class test:
pass
t = test()
def prepare_cb(obj):
#save information about the obj
uid = id(obj)
def do_some_logging(weak):
print "Object %s cleaned up" % uid
return do_some_logging
weak = weakref.ref(t, prepare_cb(t))
del t
6
http://docs.python.org/library/gc.html#gc.set_debug
你可以设置一些标志,但这些信息会写到错误输出中。
可用的标志有:
gc.DEBUG_STATS
gc.DEBUG_COLLECTABLE
gc.DEBUG_UNCOLLECTABLE
gc.DEBUG_INSTANCES
gc.DEBUG_OBJECTS
gc.DEBUG_SAVEALL
gc.DEBUG_LEAK
另外
如果你在关注代码的性能,可能想要分析一下你的代码,看看有没有耗时的循环或者函数调用。你可以使用 cProfile
或者 hotshot
来进行分析。更多信息可以查看 http://docs.python.org/library/profile.html