对于调试,我想找出在对象被销毁之前最后一次调用的特定方法的调用跟踪。
我想出了这个代码(我认为它非常聪明):
#!python3
import gc
import sys
class TrackGC:
__slots__ = [ 'is_dirty', 'last_access' ]
def __init__(self):
self.is_dirty = False
self.last_access = None
def dirty(self):
self.is_dirty = True
try:
raise RuntimeError('last access')
except RuntimeError:
self.last_access = sys.exc_info()
def __del__(self):
if self.is_dirty:
sys.excepthook(*self.last_access)
def do_stuff(obj):
obj.dirty()
obj = TrackGC()
do_stuff(obj)
print("Killing object...")
del obj
gc.collect()
我希望每次调用dirty()
时,追溯都会保存在last_access
属性中,而sys.excepthook
中对__del_
的调用会打印出来调用堆栈。
然而,在实践中,我得到了这个:
$ ./backtrace.py
Killing object...
Traceback (most recent call last):
File "./backtrace.py", line 15, in dirty
raise RuntimeError('last access')
RuntimeError: last access
为什么?我原本希望看到这个:
$ ./backtrace.py
Killing object...
Traceback (most recent call last):
File "./backtrace.py", line 28, in <module>
do_stuff(obj)
File "./backtrace.py", line 25, in do_stuff
obj.dirty()
File "./backtrace.py", line 15, in dirty
raise RuntimeError('last access')
RuntimeError: last access