我正在使用需要跟踪回调函数/方法的Python类,并且此类的实例需要在其中一个提供回调方法的类中具有引用(在其他位置)。但是,由于对象的循环引用,这会导致内存泄漏。
这在代码中更容易解释:
import psutil
import numpy as np
process = psutil.Process()
def show_mem(title):
mem = process.memory_info()
print(title + ':')
print('Real: {0:.1f}Mb'.format(mem.rss / 1024**2))
print('Virtual: {0:.1f}Mb'.format(mem.vms / 1024**2))
print()
class CallbackTracker(object):
def __init__(self):
self.callbacks = []
def add_callback(self, callback):
self.callbacks.append(callback)
class TestClass(object):
def __init__(self):
self.array = np.random.random(100000000)
self.ct = CallbackTracker()
self.ct.add_callback(self.callback)
def callback(self):
pass
def run():
t = TestClass()
show_mem('Before run()')
run()
show_mem('After run()')
运行时,返回:
Before run():
Real: 22.4Mb
Virtual: 2451.9Mb
After run():
Real: 785.4Mb
Virtual: 3214.8Mb
阵列就是让内存使用更加明显。如果我删除以下行:
self.ct.add_callback(self.callback)
然后内存泄漏就消失了:
Before run():
Real: 22.3Mb
Virtual: 2451.9Mb
After run():
Real: 22.3Mb
Virtual: 2451.9Mb
避免这种情况的最佳方法是什么?我尝试使用弱引用,但问题是在实例化类之后,回调函数似乎立即被解除引用:
import numpy as np
from weakref import proxy
class CallbackTracker(object):
def __init__(self):
self.callbacks = []
def remove_callback(self, pcallback):
print('removing callback')
self.callbacks.remove(pcallback)
def add_callback(self, callback):
self.callbacks.append(proxy(callback, self.remove_callback))
class TestClass(object):
def __init__(self):
self.array = np.random.random(100000000)
self.ct = CallbackTracker()
self.ct.add_callback(self.callback)
def callback(self):
pass
t = TestClass()
print('done with TestClass()')
给出:
removing callback
done with TestClass()
这是不好的,因为回调(在实际代码中)将不起作用。我不清楚为什么self.callback
在脚本结束之前被取消引用。什么是我原来的问题的最佳解决方案,有没有办法解决弱反射解决方案?