【问题标题】:Intermittent error while plotting graph using matplotlib "RuntimeError: main thread is not in main loop"使用 matplotlib 绘制图形时出现间歇性错误“RuntimeError:主线程不在主循环中”
【发布时间】:2017-05-17 13:36:51
【问题描述】:

我正在尝试使用我的 python 代码从不同的端点提取数据,并提供相同的数据以使用 matplotlib 绘制图形。我在读取数据时没有任何问题,但是当我通过提供数据调用绘制图形的方法时,我看到由 matplot lib 引起的间歇性错误。以下是错误详情。

Traceback (most recent call last):
  File "C:\Python35\lib\site-packages\slackbot\dispatcher.py", line 55, in _dispatch_msg_handler
    func(Message(self._client, msg), *args)
  File "C:\PycharmProjects\SlackBot\src\plugins\bot_response.py", line 248, in checkmarx
    draw_chart.riskscore_bar(top_riskscore, project_name, "output_files", "riskscore_bar.png")
  File "C:\PycharmProjects\SlackBot\src\drawchart.py", line 111, in riskscore_bar
    fig, ax = plt.subplots()
  File "C:\Python35\lib\site-packages\matplotlib\pyplot.py", line 1202, in subplots
    fig = figure(**fig_kw)
  File "C:\Python35\lib\site-packages\matplotlib\pyplot.py", line 535, in figure
    **kwargs)
  File "C:\Python35\lib\site-packages\matplotlib\backends\backend_tkagg.py", line 81, in new_figure_manager
    return new_figure_manager_given_figure(num, figure)
  File "C:\Python35\lib\site-packages\matplotlib\backends\backend_tkagg.py", line 98, in new_figure_manager_given_figure
    icon_img = Tk.PhotoImage(file=icon_fname)
  File "C:\Python35\lib\tkinter\__init__.py", line 3403, in __init__
    Image.__init__(self, 'photo', name, cnf, master, **kw)
  File "C:\Python35\lib\tkinter\__init__.py", line 3359, in __init__
    self.tk.call(('image', 'create', imgtype, name,) + options)
RuntimeError: main thread is not in main loop

我曾尝试从 stackoverflow 中查看其他带有相同错误消息的案例,但它并没有帮助我解决此问题。下面是我的代码 sn-p 调用错误。

def riskscore_bar(self, top_riskscore, project_id, output_folder, output_filename):

logger.debug("Inside method plotgraph in drawchart.py.")

y_pos = np.arange(len(project_id))
width = .4

fig, ax = plt.subplots()
graph = ax.bar(y_pos+1, top_riskscore, width, color='#feb308')
ax.set_ylabel('Risk Score')
ax.set_title('Summary')
ax.set_xticks(y_pos + 1)
ax.set_xticklabels(project_id,fontsize=5, rotation=45 )

def autolabel(rects):
    for rect in rects:
        height = rect.get_height()
        ax.text(rect.get_x() + rect.get_width()/2., 1.001*height,
                '%d' % int(height),
                ha='center', va='bottom')

autolabel(graph)
pylab.savefig(os.path.join(os.path.abspath(os.path.dirname(__file__)), '..', output_folder,output_filename))

错误似乎发生在“fig, ax = plt.subplots()”。有关如何解决此问题的任何想法?

【问题讨论】:

  • 寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定的问题或错误以及在问题本身中重现它所需的最短代码。没有明确问题陈述的问题对其他读者没有用处。请参阅:如何创建minimal reproducible example
  • 你的程序是否使用了多线程?
  • 我正在使用 slackbot 库,我可以在其中向机器人提供一些文本命令,并将结果显示到 slack 通道中。当我向 bot 发出“dashboard projectname report”之类的命令时,bot 框架将寻找“def dashboard(message)”之类的方法,我在此方法中编写所有业务代码并执行“messsage.reply(显示报告) " 在方法的末尾将结果推送到松弛通道。这在link 有更好的解释。
  • @JohanL 现在作为我的业务代码的一部分,我调用了许多其他方法来从其他端点读取数据,并从数据中绘制图形并将我从中得到的图像文件推送到松弛渠道。这是我调用方法'riskscore_bar(self,top_riskscore,project_id,output_folder,output_filename)'的地方,当我从独立文件调用此方法时,它工作正常,但从slackbot框架工作,这给了我一个间歇性错误。我不知道为什么这不起作用。
  • 我以前见过这个错误,使用 matplotlib 和线程。在我看来,matplotlib 需要在主线程中绘图,否则它将失败。我想当你单独运行你的程序时,它只有一个线程,而使用 slackbot 库会让你使用许多不同的线程。究竟如何解决这个我不知道。也许有一种方法可以让您单独或在另一个进程中(从 Python 中)运行您的绘图脚本?

标签: python matplotlib


【解决方案1】:

这可以通过在将 matplotlib.pyplot 导入为 plt 之后添加 plt.switch_backend('agg') 来解决。如下图

import matplotlib.pyplot as plt    
plt.switch_backend('agg')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-21
    • 1970-01-01
    • 2018-09-29
    • 1970-01-01
    • 2013-01-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多