无法删除 matplotlib.animation.FuncAnimation 对象

2023-12-10

编辑/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(...)回归、场景animid 已经被回收了。

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()))

back references

所以,有一个matplotlib.backends.backend_qt4.TimerQT还是有参考价值的。有什么办法去掉吗?


要弄清楚这里发生了什么,需要深入了解动画模块和两个回调注册表的工作原理。

当您创建Animation对象,它将回调注册到 mpl 回调注册表中draw_event这样在第一次绘制画布之后Animation创建对象后,定时动画会自行设置(通过将回调注册到计时器对象中)并将回调注册到 mpl 回调注册表中close_event拆除计时器。

mpl 回调注册表对传入的可调用对象进行一系列内省,并将绑定方法重建为对象和相关函数的弱引用。因此,如果您创建一个动画对象但不保留对其的引用,则它的引用计数将为零,mpl 回调注册表中对其的弱引用将失败,并且动画将永远不会开始。

定时器的工作方式Qt是你注册一个可调用的,它被添加到一个列表中(我从底部的图表中得到这个),所以它持有对Animation对象,因此删除对象中保存的引用不足以将引用计数驱动为零。对于计时器回调来说,这可能是一个功能,而不是一个错误。

我现在理解的工件意味着你正在创建第二个Animation对象,你得到的是它们都是并行运行的(我不确定我期望在那里发生什么)。

停止运行Animation并使用私有方法(应该是公共的)将其从计时器的回调列表中删除_stop这就是负责拆卸的原因(并且是在close_event).

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无法删除 matplotlib.animation.FuncAnimation 对象 的相关文章

  • 多索引上的 pandas dataframe groupby

    我正在使用 Pandas dataframe 来读取 Excel 文件并对其进行一些操作 我有一个包含多行的标题 现在我想按几个列值进行分组 但是我无法找到解决方案 Excel 示例 name address contact info fi
  • 如何绘制日期和月份

    我有一张随时间变化的每日趋势图表 年份与此处无关 我只想显示日期和月份 我知道你可以显示年份和月份 但事实并非如此 我尝试创建一个名为 Day Month 的新变量 import datetime as dt df Day df date
  • 删除网格线,但保留框架(matplotlib 中的 ggplot2 样式)

    使用 Matplotlib 我想删除图中的网格线 同时保留框架 即轴线 我已经尝试过下面的代码和其他选项 但我无法让它工作 如何在删除网格线的同时保留框架 我这样做是为了在 matplotlib 中重现 ggplot2 图 我在下面创建了一
  • 使用Python下载YouTube视频到某个目录

    我已尝试使用以下代码在 YouTube 中下载视频并且它可以正常工作 但我想将视频保存在特定位置 现在它正在将视频保存在C Users Download 如果我想将视频保存在桌面上 我需要对代码进行哪些更改 from future impo
  • 清除pyqt中布局中的所有小部件

    有没有办法清除 删除 布局中的所有小部件 self plot layout QtGui QGridLayout self plot layout setGeometry QtCore QRect 200 200 200 200 self r
  • Python lmfit 在加权拟合后将卡方减小得太小

    我正在 Python 2 7 中运行 fitlmfit通过以下代码使用一些测试数据 我需要权重为1 y 使用 Leven Marq 例程 我已经定义了权重并在这里使用它们 from future import division from n
  • 如何缩放图像的一部分并插入到 matplotlib 中的同一图中

    我想缩放数据 图像的一部分并将其绘制在同一个图中 看起来有点像这个图 是否可以在同一图中插入缩放图像的一部分 我认为可以用子图绘制另一个图形 但它绘制了两个不同的图形 我还阅读了添加补丁以插入矩形 圆形 但不确定将图像的一部分插入到图中是否
  • logger.warning("MSVC is not support") 在 Windows 10 上安装 pystan 时出错

    我的目标是在我的 Windows 10 计算机上安装 fbprophet 我正在尝试使用 pip 安装 pystan 先知的主要依赖项 但大约一分钟后 我收到以下错误 Traceback most recent call last File
  • Python 类中的继承顺序

    我有课ExampleSim它继承自基类Physics class Physics object arg1 arg1 def physics method print physics method class ExampleSim Physi
  • 使用自定义颜色渐变填充两条线之间的区域

    我正在做一项几乎已经完成的作业 但我想对其添加一些小改动 尝试使用基于温度的颜色图而不是简单的颜色来填充两条线之间的区域 绘制线条的方式本质上使它们成为独立的实体 所以我知道我可能需要两个彼此相遇或重叠的颜色图来完成此任务 但我不太确定如何
  • spacy 是否将令牌列表作为输入?

    我想使用 spacy 的 POS 标记 NER 和依存解析 而不使用单词标记化 事实上 我的输入是代表一个句子的标记列表 我想尊重用户的标记化 无论是使用 spacy 还是任何其他 NLP 包 这是否可能 现在 我使用这个基于 spacy
  • 如何使用 python 标准库 zipfile 检查 zip 文件是否已加密?

    我正在使用 python 的标准库 zipfile 来测试存档 zf zipfile ZipFile archive name if zf testzip None checksum OK True 我收到这个运行时异常 File pack
  • 绘制 Pandas OLS 线性回归结果

    我将如何绘制我从 pandas 进行的线性回归的线性回归结果 import pandas as pd from pandas stats api import ols df pd read csv Samples csv index col
  • python 2.7模块pandas未安装“无法导入名称哈希表”

    我尝试在论坛 谷歌上寻找这个问题的答案 但我找不到任何东西 我的问题是这样的 来自 python 控制台 gt gt gt import pandas cannot import name hashtable Traceback most
  • 即使在 GC Collect 和 WaitForPendingFinalizers 之后,窗口对象在关闭后也未释放?

    这是一个简单的测试应用程序 可帮助了解 WPF 内存使用情况 我想了解的关键是为什么MainWindow即使在关闭并等待 GC 完成之后 仍然被引用并且它的内存没有被释放 参见下面的代码清单 文本 MainWindow Finalizer
  • Redis - 错误:值不是有效的浮点数

    我在 Redis 中有一个排序集 我试图通过在Python代码中使用zincrby来更新特定元素的计数器值 例如 conn zincrby usersSet float 1 user1 但它显示错误为 错误 值不是有效的浮点数 我在 cli
  • 检测计算机何时解锁 Windows

    我用过这个优秀的方法 https stackoverflow com questions 20733441 lock windows workstation using python 20733443锁定 Windows 计算机 那部分工作
  • matplotlibplot_曲面图

    matplotlib 教程提供了如何绘制球面的一个很好的示例 from mpl toolkits mplot3d import Axes3D import matplotlib pyplot as plt import numpy as n
  • 如何生成给定范围内的回文数列表?

    假设范围是 1 X 120 这是我尝试过的 gt gt gt def isPalindrome s check if a number is a Palindrome s str s return s s 1 gt gt gt def ge
  • NameError:名称“urllib”未定义”

    CODE import networkx as net from urllib request import urlopen def read lj friends g name fetch the friend list from Liv

随机推荐