Karen Tracey wrote: > I originally posted this to the user's list but got no response there. > As I think there's a bug in matplotlib here, I'm re-trying on the > development list. Here's what I sent to -users back on Mar 13:
Karen, (I saw your question to the users group, and was hoping someone more knowledgeable than myself about threading problems would reply to you.) http://www.mail-archive.com/matplotlib-us...@lists.sourceforge.net/msg06152.html I don't think there has been any progress on this question since it came up a year ago in the above thread. Evidently it is something that needs more attention. I would say that you have found a bug, and there are probably many more. There are global objects outside the pyplot interface; maybe they provide opportunities for threads to trip over each other. A reasonable goal would be to have matplotlib be thread-safe at least when the pure OO interface is used, and possibly with some additional restrictions such as "don't mess with rcParams when more than one thread might be running". I suspect this will take some time and effort to achieve--and I don't know who might be able to put in that time and effort. What might help would be a simple but brutal testing framework, independent of web servers etc., that would be likely to make mpl fail quickly unless it really is thread-safe. Maybe you can provide such a test program? And if you are willing to dive into mpl internals and come up with solutions for thread problems, that's even better. For your immediate needs, I suggest that you use only the OO interface (which means that you won't import pylab or pyplot, and so won't use the figure() function), and/or use a mutex as you describe below. (I don't think that dumping "figure" in itself will help with the problem you have run into so far; you will still need the mutex. And if the mutex locks all your plotting, then you probably won't hit any other mpl threading problems.) If you do keep using the figure() function (or any related aspect of the pyplot interface) then be sure to explicitly close each figure. Otherwise your process will chew up all available memory. Eric > > I am using matplotlib's object-oriented API to dynamically generate some > graphs served by a web site. The web site is built with Django and I > have generally followed the cookbook example I found here: > http://www.scipy.org/Cookbook/Matplotlib/Django for serving matplotlib > figures under Django. Specifically my code looks like this: > > from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas > from matplotlib.figure import Figure > > def generate_png(request, f, year, cid, pid, ic): > > # ...snipped code that generates the data to graph... > > fig = Figure() > ax = fig.add_subplot(111) > ax.set_title(fig_title) > ax.set_xlabel("Score") > ax.set_ylabel("Frequency") > n, bins2, patches = ax.hist(vals, bins, facecolor='blue', > edgecolor='blue') > if x is not None: > patches[x].set_facecolor('red') > patches[x].set_edgecolor('red') > fig.legend((patches[x],), ('%s (%d)' % (cname, cval),), 'lower > left') > canvas = FigureCanvas(fig) > canvas.print_png(f) > > # ... snip remainder ... > > This works fine, except when I run it under a multi-threaded web server > (Apache with mod_wsgi in daemon mode with multi-threaded processes) it > sometimes (not always) fails with this traceback: > > File > "/home/kmt/django/Django-1.1-alpha-1/django/core/handlers/base.py", line > 86, in get_response > response = callback(request, *callback_args, **callback_kwargs) > File "/home/kmt/software/web/xword/acpt/views.py", line 321, in get_png > response = generate_png(request, f, year, cid, pid, ic) > File "/home/kmt/software/web/xword/acpt/views.py", line 308, in > generate_png > canvas.print_png(f) > File > "/usr/lib/python2.5/site-packages/matplotlib/backends/backend_agg.py", > line 305, in print_png > FigureCanvasAgg.draw(self) > File > "/usr/lib/python2.5/site-packages/matplotlib/backends/backend_agg.py", > line 261, in draw > self.figure.draw(self.renderer) > File "/usr/lib/python2.5/site-packages/matplotlib/figure.py", line 765, > in draw > legend.draw(renderer) > File "/usr/lib/python2.5/site-packages/matplotlib/legend.py", line 215, > in draw > t.draw(renderer) > File "/usr/lib/python2.5/site-packages/matplotlib/text.py", line 329, > in draw > ismath=self.is_math_text(line)) > File > "/usr/lib/python2.5/site-packages/matplotlib/backends/backend_agg.py", > line 113, in draw_text > self._renderer.draw_text_image(font.get_image(), int(x), int(y) + 1, > angle, gc) > RuntimeError: You must call .set_text() before .get_image() > > I'm not at all familiar with the internals (truly I'm barely familiar > with the public APIs) of matplotlib but it appears from this exception > that internally there's a 'font' object being shared between threads > here, such that one thread can come in and change the font state > resulting in a subsequent error in a different thread that was also in > the middle of using that font object? If I protect that block of code > above with a thread lock so that only one thread is allowed in at a > time, the problem goes away. > > For reference I'm using the latest matplotlib available in the Ubuntu > Intrepid (8.10) repositories, which looks to be 0.98.3. In a brief scan > I didn't see anything relevant listed in the "what's new" page for > 0.98.4 (and can't find a "what's new in 0.98.5" on the matplotlib web > site though that is what is listed as most recent?). Nor can I find > anything that looks similar logged as a bug in the tracker. > > Is there something (besides bracketing all access to the matplotlib code > with a thread mutex) that I should be doing to make my use of matplotlib > thread safe or does it seem like there's a multi-threading bug in > matplotlib here? > > Apologies if this is the wrong list and there is in fact something I > ought to be doing in my code (other than using a mutex) to prevent this > -- I haven't been able to find anything. My impression from various doc > I've read is the object-oriented API is supposed to be thread-safe. Is > that true? If so should I file a ticket for this? > > Thanks for any feedback, > Karen > > > ------------------------------------------------------------------------ > > ------------------------------------------------------------------------------ > > > ------------------------------------------------------------------------ > > _______________________________________________ > Matplotlib-devel mailing list > Matplotlib-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/matplotlib-devel ------------------------------------------------------------------------------ _______________________________________________ Matplotlib-devel mailing list Matplotlib-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-devel