33
votes

I'm trying to make my data analysis and reports less eye stabbing and more graphical with automatically generated graph-files, and to do this I've been playing with matplotlib/pyplot/pylab. Works brilliantly, but when I try to run it on a headless server...

tkinter.TclError: no display name and no $DISPLAY environment variable

For this application I only use PyLab, but after a little google, I added the below to before the pylab import:

import matplotlib
matplotlib.use("Agg")

Which should have changed the backend, but to no effect.

Any ideas what I'm doing wrong?

The remote machine does have X-forwarding capabilities, but since this application shouldn't NEED to display anything, I believe the usual ssh -X hack is overkill.

Examples:Fiendish Deception

Example working code on same machine

import matplotlib
matplotlib.use("Agg")
import numpy as np
import pylab as pl


xvals=np.arange(100)
yvals=np.cumsum(np.random.random(100))
yvals[-10:]=0
yvals=np.log(yvals)
pl.close()

pl.plot(xvals,yvals)
pl.xlabel("X")
pl.ylabel("Y")
pl.title("Title")

pl.savefig("testgraph.png")

Non-working real code

import matplotlib
matplotlib.use("Agg")
import numpy as np
import pylab as pl
import utility as util
import os

... non graph stuff...
def graph_p(self):
    pl.close()
    channels=range(self.p.shape[0])
    for line in range(self.p.shape[1]):
        yvals=np.ma.masked_invalid(map(util.watts_to_dbmhz,self.p[:,line]))
        pl.plot(channels,yvals) #Error says it occurs here
    pl.xlabel("Subchannel Index")
    pl.ylabel("Power (dbmhz)")
    pl.title("Plot of per-tone power assignments for %d lines"%self.p.shape[1])
    pl.savefig(self.dest+self.scenario+'-power.png')

Nothing else touches pyplot.

3
It is very strange, indeed. Can you post a minimum (non-)working example? The Agg backend should not need X. - Andrea Spadaccini
Updated with minimal example, but now I can't break it! - Bolster

3 Answers

25
votes

Everything you describe sounds correct. What happens when you run this:

import matplotlib
matplotlib.use('Agg')
import pylab
pylab.plot([1,2], [3,4], linestyle='-')
pylab.savefig('foo.png')

In my environment it produces this (I scaled it down):

enter image description here

12
votes

Turns out a utility file (not mine!) was pulling in pylab for something else. Shifted the matplotlib backend selection into the initial page.

11
votes

Try importing matplotlib and setting the Agg backend before importing numpy:

import matplotlib
matplotlib.use("Agg")