weakref (WeakKeyDictionary) 到框架 (FrameType) 对象
weakref (WeakKeyDictionary) to frame (FrameType) objects
我想要一个从活动帧 (FrameType
) 对象到某些数据的字典映射。活动意味着它在当前执行堆栈跟踪中。
但是,保留对框架对象的引用不是一个好主意,因为这也会保留非活动框架,并且由于对所有局部变量的所有引用,很快就会耗尽内存。
自然的解决方案是对框架对象使用弱引用,或者更具体地说 WeakKeyDictionary
。
但是,目前无法为框架对象创建弱引用:
import weakref
import sys
f = sys._getframe()
weakref.ref(f)
产量
TypeError: cannot create weak reference to 'frame' object
我假设这是 CPython 实现细节?
那么,有哪些选择呢?
我可能无论如何都可以创建引用,但是当它们不再活动时,请尝试尽快清理它们。 How do I actually check if a frame object is active?
这是一个疯狂的想法:如果您不能保存对框架的引用,请让框架保存对您的引用。
class FrameDict:
def __init__(self):
self._data_by_frame_id = {}
def __setitem__(self, frame, data):
frame_id = id(frame)
# Make the frame hold a reference to a KeyDeleter, so when the frame
# dies, the KeyDeleter dies, and the frame is removed from the dict
deleter = KeyDeleter(self._data_by_frame_id, frame_id)
frame.f_locals[deleter] = deleter
self._data_by_frame_id[frame_id] = data
def __getitem__(self, frame):
frame_id = id(frame)
return self._data_by_frame_id[frame_id]
class KeyDeleter:
def __init__(self, mapping, key):
self.mapping = mapping
self.key = key
def __del__(self):
del self.mapping[self.key]
演示:
import inspect
def new_frame():
return inspect.currentframe()
frame_dict = FrameDict()
frame = new_frame()
frame_dict[frame] = 'foobar'
print(frame_dict[frame]) # foobar
del frame
print(frame_dict._data_by_frame_id) # {}
我想要一个从活动帧 (FrameType
) 对象到某些数据的字典映射。活动意味着它在当前执行堆栈跟踪中。
但是,保留对框架对象的引用不是一个好主意,因为这也会保留非活动框架,并且由于对所有局部变量的所有引用,很快就会耗尽内存。
自然的解决方案是对框架对象使用弱引用,或者更具体地说 WeakKeyDictionary
。
但是,目前无法为框架对象创建弱引用:
import weakref
import sys
f = sys._getframe()
weakref.ref(f)
产量
TypeError: cannot create weak reference to 'frame' object
我假设这是 CPython 实现细节?
那么,有哪些选择呢?
我可能无论如何都可以创建引用,但是当它们不再活动时,请尝试尽快清理它们。 How do I actually check if a frame object is active?
这是一个疯狂的想法:如果您不能保存对框架的引用,请让框架保存对您的引用。
class FrameDict:
def __init__(self):
self._data_by_frame_id = {}
def __setitem__(self, frame, data):
frame_id = id(frame)
# Make the frame hold a reference to a KeyDeleter, so when the frame
# dies, the KeyDeleter dies, and the frame is removed from the dict
deleter = KeyDeleter(self._data_by_frame_id, frame_id)
frame.f_locals[deleter] = deleter
self._data_by_frame_id[frame_id] = data
def __getitem__(self, frame):
frame_id = id(frame)
return self._data_by_frame_id[frame_id]
class KeyDeleter:
def __init__(self, mapping, key):
self.mapping = mapping
self.key = key
def __del__(self):
del self.mapping[self.key]
演示:
import inspect
def new_frame():
return inspect.currentframe()
frame_dict = FrameDict()
frame = new_frame()
frame_dict[frame] = 'foobar'
print(frame_dict[frame]) # foobar
del frame
print(frame_dict._data_by_frame_id) # {}