【问题标题】:Matplotlib - Tcl_AsyncDelete: async handler deleted by the wrong thread?Matplotlib - Tcl_AsyncDelete:异步处理程序被错误的线程删除?
【发布时间】:2015-01-24 16:07:18
【问题描述】:

我问这个问题是因为我无法解决 Python/Django 中的一个问题(实际上在纯 Python 中没问题),这导致 RuntimeError: tcl_asyncdelete async handler deleted by the wrong thread。这在某种程度上与我在 Django 中渲染matplotlib 绘图的方式有关。我的做法是:

...
import matplotlib.pyplot as plt
...
fig = plt.figure()
...
plt.close()

我极大地减少了我的代码。但问题是——即使我只有一行代码:

fig = plt.figure()

我看到这个 RuntimeError 发生了。我希望我能解决这个问题,如果我知道在 Python/Django 中关闭/清理/销毁绘图的正确方法。

【问题讨论】:

  • 你能发布回溯吗?
  • 我在 Pyramid 1.3.4 / Python 2.7 中遇到了同样的问题,仅此而已 - Exception RuntimeError: RuntimeError('main thread is not in main loop',) in > 的方法 PhotoImage.__del__ 忽略 Tcl_AsyncDelete: 异步处理程序被错误的线程删除

标签: python django matplotlib


【解决方案1】:

matplotlib 默认使用 TK gui 工具包,当你在不使用工具包的情况下渲染图像(即渲染到文件或字符串中)时,matplotlib 仍然会实例化一个不显示的窗口,从而导致各种问题。为了避免这种情况,您应该使用 Agg 后端。可以这样激活——

import matplotlib
matplotlib.use('Agg')
from matplotlib import pyplot

更多信息请参考matplotlib文档——http://matplotlib.org/faq/howto_faq.html#matplotlib-in-a-web-application-server

【讨论】:

  • 不,我不会将它们渲染成图像。我用 base64 对它们进行编码并在浏览器中呈现。
  • 我的意思是你没有使用TK工具包,我会澄清我的答案。
  • 有点晚了,但这为我解决了一个非常微妙和烦人的错误。谢谢! pyplot 的错误消息在这方面肯定会更有帮助。
  • @AlexVolkov 非常感谢,这为我解决了一个如此神秘的错误。没有什么只是Tcl_AsyncDelete: async handler deleted by the wrong thread,我使用的是flask、matplotlib、python-pptx。我什至不知道 matplotlib 是造成这种情况的原因。
【解决方案2】:

上述(已接受)答案是终端环境中的解决方案。如果您在 IDE 中进行调试,您可能仍想使用“TkAgg”来显示数据。为了防止这个问题,应用这两个简单的规则:

  1. 每次显示数据时,启动一个新的fig = plt.figure()
  2. 不要手动关闭旧图(例如,使用调试模式时)

示例代码:

import matplotlib
matplotlib.use('TkAgg')
from matplotlib import pyplot as plt

fig = plt.figure()
plt.plot(data[:,:,:3])
plt.show()

这在 MacOS 和 PyCharm IDE 下被证明是一个很好的中间解决方案。

【讨论】:

  • 我照你说的做了。不过,同样的问题。我正在使用 Pycharm Pro 2020。
  • 另外,如果你想在之前的情节之上绘制呢?你不想实例化一个新图形
  • 那我该如何关闭图呢?我正在使用控制台并经常收到此错误,通常是在使用制表符完成时。
【解决方案3】:

如果您在调试时不需要显示绘图,则可以使用以下方法:

import matplotlib
matplotlib.use('Agg')
from matplotlib import pyplot as plt

但是,如果您想在调试的同时进行绘图,则需要执行 3 个步骤:

1.将后端保持在“TKAgg”,如下所示:

import matplotlib
matplotlib.use('TKAgg')
from matplot.lib import pyplot as plt

或者干脆

import matplotlib.pyplot as plt

2.正如Fábio 也提到的,您需要为每个图形#i 添加 fig(no.#i)=plt.figure(no.#i)。如下图#1的例子,添加:

fig1 = plt.figure(1)
plt.plot(yourX,yourY)
plt.show()

3.添加断点。您至少需要添加两个断点,一个位于代码开头的某个位置(第一个图之前),另一个断点位于您希望绘制所有图的点(第二个断点之前)。所有图形都被绘制出来,您甚至不需要手动关闭任何图形。

【讨论】:

    【解决方案4】:

    对我来说,这是因为在 Tensorboard 的服务器连续运行一周之后,Matplotlib 和 Tensorboard 并行访问数据。

    Rebotting tensorboard tensorboard --logdir . --samples_per_plugin images=100 为我解决了这个问题。

    【讨论】:

      【解决方案5】:

      我在我的 tkinter 应用程序中使用 matplotlib 实时绘制图形时遇到了这个问题。

      我找到的最简单的解决方案是始终删除子图。我发现你不需要实例化一个新的图形,你只需要删除旧的子图(使用 del subplot),然后重新制作它。

      在绘制新图之前,请确保删除旧的子图。 示例:

      f = Figure(figsize=(5,5), dpi=100)
      a = f.add_subplot(111)
      (For Loop code that updates graph every 5 seconds):
          del a #delete subplot
          a = f.add_subplot(111) #redefine subplot
      

      找到这个简单的解决方案来修复这个“异步处理程序错误”非常痛苦,我希望这对其他人有帮助:)

      【讨论】:

        猜你喜欢
        • 2021-12-23
        • 1970-01-01
        • 2015-01-20
        • 2019-01-26
        • 1970-01-01
        • 2013-09-10
        • 2017-10-24
        • 1970-01-01
        • 2014-07-04
        相关资源
        最近更新 更多