2

I am trying to pull data from different end points using my python code and feeding the same data to plot a graph using matplotlib. I dont have any problem in reading the data but when i invoke the methods to plot graph by feeding the data i see intermittent error caused by matplot lib. below are the error details.

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

I have tried looking into other cases from stackoverflow with same error messages, but it didnt help me fix this. Below is my code snippet that invokes an error.

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

The error seems to occur at "fig, ax = plt.subplots()". any ideas on how this can be fixed?

SK R
  • 21
  • 2
  • Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. See: How to create a [mcve]. – ImportanceOfBeingErnest May 17 '17 at 15:34
  • Is your program using multiple threads? – JohanL May 17 '17 at 20:28
  • I am using the slackbot library, where i can give some text commands to the bot and get the results displayed into the slack channel. when i give a command like "dashboard projectname report" to the bot, bot framework will look for the method like "def dashboard(message)" i write all my business code in this method and do a "messsage.reply(display report)" at the end of the method to push the result to slack channel. This is better explained at [link](https://github.com/BeepBoopHQ/python-slack-bot). – SK R May 18 '17 at 05:03
  • @JohanL Now as part of my business code i call lot of other methods to read data from other end points and also to plot graphs from the data and push the image file i got out of it to slack channel. This is where i call the method 'riskscore_bar(self, top_riskscore, project_id, output_folder, output_filename)' This works fine when i call this method from a standalone file but from slackbot frame work this gives me an intermittent error. I have no clue why this is not working. – SK R May 18 '17 at 05:10
  • I have seen this error before, using `matplotlib` with threads. It appears to me that `matplotlib` is required to plot in the main thread, or it will fail. I guess that when you run your program stand alone, it has only one thread, whereas using the slackbot library will make you use a number of different threads. Exactly how to get around this I don't know. Perhaps there is a way for you to run your plot script stand alone or in another process (from within Python)? – JohanL May 18 '17 at 12:09
  • Thanks @JohanL, at the moment i dont see a way around to run my plot script in another process or in standalone mode. I am completely struck. – SK R May 18 '17 at 21:27

1 Answers1

0

this can be solved by adding plt.switch_backend('agg') below right after you import matplotlib.pyplot as plt. As shown below

import matplotlib.pyplot as plt    
plt.switch_backend('agg')
Akanni
  • 924
  • 9
  • 10