Pylab in a multi-threaded application server?

I am using the method below to dynamically generate pie charts in my TurboGears/CherryPy web app. Everything works fine until I increase the number of application threads allowed to > 1.

Then all manner of wierdness occurs. Pies charts which are not scaled properly, which have the various wedges scaled differently from each other, and incomplete pie charts.

Am I doing something wrong?

  def pie_chart(self, **kw):
    figure(1, figsize=(0.75,0.75), frameon=False) ax = axes([0.1, 0.1, 0.8, 0.8])
    labels = 'Contract', 'Billable', 'Unbillable', 'Nonbill'
    billable=float(kw['billable'])
    contract=float(kw['contract'])
    unbillable=float(kw['unbillable'])
    nonbill=float(kw['nonbill'])
    fracs = [contract,billable, unbillable,nonbill]
    fig = pie(fracs, shadow=False, colors=('#70A0A0', '#C0F090','#C03030', '#FFFFFF'))
    fname = os.tmpnam() + ".png"
    savefig(fname)
    f=open(fname,'r')
    x=f.read()
    f.close()
    os.remove(fname)
    pylab.close()
    return (x)

Steve,

I think the short answer is that the pylab interface is inherently single-threaded; it is intended to facilitate interactive plotting. It has a single list of figures, a concept of a single current figure, and within that a single current axes. If you use more than one thread, then thread B is liable to change the current figure or axes while thread A is in the middle of doing something with it. It is a recipe for chaos.

Careful adherence to the Object-oriented interface that underlies the pylab interface should mostly solve the problem, because then each thread should be operating on its own figure and axes. I said "mostly" because there is still the global rcParams dictionary; you will need to be sure that your plotting threads treat it as read-only. There may be other such things that have not occurred to me.

An alternative would be to use a locking mechanism to ensure that your plotting function runs from start to end without interruption by another thread.

Eric

Steve Bergman wrote:

···

I am using the method below to dynamically generate pie charts in my TurboGears/CherryPy web app. Everything works fine until I increase the number of application threads allowed to > 1.

Then all manner of wierdness occurs. Pies charts which are not scaled properly, which have the various wedges scaled differently from each other, and incomplete pie charts.

Am I doing something wrong?

def pie_chart(self, **kw):
   figure(1, figsize=(0.75,0.75), frameon=False) ax = axes([0.1, 0.1, 0.8, 0.8])
   labels = 'Contract', 'Billable', 'Unbillable', 'Nonbill'
   billable=float(kw['billable'])
   contract=float(kw['contract'])
   unbillable=float(kw['unbillable'])
   nonbill=float(kw['nonbill'])
   fracs = [contract,billable, unbillable,nonbill]
   fig = pie(fracs, shadow=False, colors=('#70A0A0', '#C0F090','#C03030', '#FFFFFF'))
   fname = os.tmpnam() + ".png"
   savefig(fname)
   f=open(fname,'r')
   x=f.read()
   f.close()
   os.remove(fname)
   pylab.close()
   return (x)

-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Eric Firing wrote:

An alternative would be to use a locking mechanism to ensure that your plotting function runs from start to end without interruption by another thread.

Thanks. I'm now controlling access with a lock object and it's working fine.

-Steve