编辑/TL;博士:看起来好像有一个matplotlib.backends.backend_qt4.TimerQT
包含对我的 FuncAnimation 对象的引用的对象。如何删除它以释放 FuncAnimation 对象?
1 - 一些背景知识
我正在尝试对使用 matplotlib 生成的绘图进行动画处理。我使用 matplotlib.animation.FuncAnimation。
该动画图包含在FigureCanvasQTAgg(matplotlib.backends.backend_qt4agg)中,即。 PyQt4 小部件。
class ViewerWidget(FigureCanvasQTAgg):
def __init__(self, viewer, parent):
# viewer is my FuncAnimation, encapsulated in a class
self._viewer = viewer
FigureCanvasQTAgg.__init__(self, viewer.figure)
当 GUI 中的配置发生更改时,该图将被清除 (figure.clf()
)及其子图(轴和线)被新的替换。
2 - 类的源代码Viewer
(封装FuncAnimation
)
这是我的方法中最相关的部分Viewer.show(...)
,实例化 FuncAnimation
2.a - 首先,我尝试:
animation.FuncAnimation(..., blit=True)
当然,该实例立即被垃圾收集
2.b - 然后,我将其存储在类变量中:
self._anim = animation.FuncAnimation(..., blit=True)
它适用于第一个动画,但是一旦配置发生变化,我就会在新动画中出现以前动画的伪影
2.c - 所以我手动添加了一个del
:
# Delete previous FuncAnimation if any
if self._anim:
del self._anim
self._anim = animation.FuncAnimation(..., blit=True)
没有改变
2.d - 经过一些调试后,我检查了垃圾收集器:
# DEBUG: check garbage collector
def objects_by_id(id_):
for obj in gc.get_objects():
if id(obj) == id_:
return obj
self._id.remove(id_)
return "garbage collected"
# Delete previous FuncAnimation if any
if self._anim:
del self._anim
# DEBUG
print "-"*10
for i in self._id.copy():
print i, objects_by_id(i)
print "-"*10
self._anim = animation.FuncAnimation(self._figure_handler.figure,
update,
init_func=init,
interval=self._update_anim,
blit=True)
# DEBUG: store ids only, to enable object being garbage collected
self._anim_id.add(id(anim))
修改3次配置后,显示:
----------
140488264081616 <matplotlib.animation.FuncAnimation object at 0x7fc5f91360d0>
140488264169104 <matplotlib.animation.FuncAnimation object at 0x7fc5f914b690>
140488145151824 <matplotlib.animation.FuncAnimation object at 0x7fc5f1fca750>
140488262315984 <matplotlib.animation.FuncAnimation object at 0x7fc5f8f86fd0>
----------
因此,它确认没有任何 FuncAnimation 被垃圾收集
2.e - 最后一次尝试,使用weakref:
# DEBUG: check garbage collector
def objects_by_id(id_):
for obj in gc.get_objects():
if id(obj) == id_:
return obj
self._id.remove(id_)
return "garbage collected"
# Delete previous FuncAnimation if any
if self._anim_ref:
anim = self._anim_ref()
del anim
# DEBUG
print "-"*10
for i in self._id.copy():
print i, objects_by_id(i)
print "-"*10
anim = animation.FuncAnimation(self._figure_handler.figure,
update,
init_func=init,
interval=self._update_anim,
blit=True)
self._anim_ref = weakref.ref(anim)
# DEBUG: store ids only, to enable object being garbage collected
self._id.add(id(anim))
这次,日志令人困惑,我不确定发生了什么。
----------
140141921353872 <built-in method alignment>
----------
----------
140141921353872 <built-in method alignment>
140141920643152 Bbox('array([[ 0., 0.],\n [ 1., 1.]])')
----------
----------
140141921353872 <built-in method alignment>
140141920643152 <viewer.FftPlot object at 0x7f755565e850>
140141903645328 Bbox('array([[ 0., 0.],\n [ 1., 1.]])')
----------
(...)
我的在哪里<matplotlib.animation.FuncAnimation object at 0x...>
?
不再有以前的动画工件,到目前为止一切都很好,但是...... FuncAnimation 不再能够执行“更新”。只有“init”部分。我的猜测是 FuncAnimation 一旦方法被垃圾收集Viewer.show(...)
回归、场景anim
id 已经被回收了。
3 - Help
我不知道从这里往哪里看。有什么建议吗?
EDIT:我安装了objgraph为了可视化所有对 FuncAnimation 的反向引用,我得到了这个:
import objgraph, time
objgraph.show_backrefs([self._anim],
max_depth=5,
filename="/tmp/debug/func_graph_%d.png"
% int(time.time()))
所以,有一个matplotlib.backends.backend_qt4.TimerQT
还是有参考价值的。有什么办法去掉吗?