2013-01-22 19 views
11

I miei tag e il titolo indicano chiaramente il mio problema. Voglio usare matplotlib per creare grafici in tempo reale in Google App Engine. Ho letto lo documentation e ho cercato su SO e Google. Ho trovato un post, che punta a this working demo. Ma quando provo da solo, non funziona per me.Utilizzo di matplotlib in GAE

Ho creato una semplice applicazione, costituita esclusivamente da un gestore di script hello_world.py

import numpy as np 
import os 
import sys 
import cStringIO 

print "Content-type: image/png\n" 

os.environ["MATPLOTLIBDATA"] = os.getcwdu() # own matplotlib data 
os.environ["MPLCONFIGDIR"] = os.getcwdu() # own matplotlibrc 
import matplotlib.pyplot as plt 

plt.plot(np.random.random((20))) #imshow(np.random.randint((10,10))) 

sio = cStringIO.StringIO() 
plt.savefig(sio, format="png") 
sys.stdout.write(sio.getvalue()) 

e aa file di configurazione app.yaml

application: helloworldtak 
version: 1 
runtime: python27 
api_version: 1 
threadsafe: no 

handlers: 
- url: /.* 
    script: hello_world.py 

libraries: 
- name: numpy 
    version: "latest" 
- name: matplotlib 
    version: "latest" 

voglio tracciare qualcosa e quindi restituire il contenuto come png-image. Questa procedura funziona bene per un normale web server come Apache o IIS, l'ho fatto un milione di volte.

Il problema è piuttosto: quando si esegue il mio script localmente all'interno del server di sviluppo, ottengo un errore che è probabilmente dovuto alla mia MPL versione 1.1.1, che è solo "sperimentale" in GAE. Ma quando distribuisco la mia app su GAE, ottengo un errore completamente diverso, non correlato.

Guardando gli sguardi, il traceback è:

Traceback (most recent call last): 
    File "/base/data/home/apps/s~helloworldtak/1.364765672279579252/hello_world.py", line 16, in <module> 
    import matplotlib.pyplot as plt 
    File "/python27_runtime/python27_lib/versions/third_party/matplotlib-1.1.1/matplotlib/pyplot.py", line 23, in <module> 
    from matplotlib.figure import Figure, figaspect 
    File "/python27_runtime/python27_lib/versions/third_party/matplotlib-1.1.1/matplotlib/figure.py", line 18, in <module> 
    from axes import Axes, SubplotBase, subplot_class_factory 
    File "/python27_runtime/python27_lib/versions/third_party/matplotlib-1.1.1/matplotlib/axes.py", line 14, in <module> 
    import matplotlib.axis as maxis 
    File "/python27_runtime/python27_lib/versions/third_party/matplotlib-1.1.1/matplotlib/axis.py", line 10, in <module> 
    import matplotlib.font_manager as font_manager 
    File "/python27_runtime/python27_lib/versions/third_party/matplotlib-1.1.1/matplotlib/font_manager.py", line 1324, in <module> 
    _rebuild() 
    File "/python27_runtime/python27_lib/versions/third_party/matplotlib-1.1.1/matplotlib/font_manager.py", line 1278, in _rebuild 
    fontManager = FontManager() 
    File "/python27_runtime/python27_lib/versions/third_party/matplotlib-1.1.1/matplotlib/font_manager.py", line 995, in __init__ 
    self.defaultFont['ttf'] = self.ttffiles[0] 
IndexError: list index out of range 

Sembra avere a che fare qualcosa con il font-cache di MPL. Ho letto nei documenti che la memorizzazione nella cache e l'accesso ai file è uno dei problemi con MPL in GAE, ma ovviamente l'importazione funziona per gli altri.

Cosa sto sbagliando?

Modifica Sulla base della risposta qui sotto, ho cambiato il mio codice di essere

import numpy as np 
import cStringIO 
import matplotlib.pyplot as plt 

import webapp2 

class MainPage(webapp2.RequestHandler): 
    def get(self): 
     plt.plot(np.random.random((20)),"r-") 
     sio = cStringIO.StringIO() 
     plt.savefig(sio, format="png") 
     self.response.headers['Content-Type'] = 'image/png' 

     self.response.out.write(sio.getvalue()) 

app = webapp2.WSGIApplication([('/', MainPage)], 
           debug=True) 

e come questo, sta funzionando.

+0

Per essere chiari, non riesce in localhost? e da dove hai preso il tuo file app.yaml? (Python 7 normalmente chiama lo script principale come hello_world.app) –

+0

L'ho creato secondo la guida "Getting started". Ho quindi migrato a una versione 2.7 in base al manuale. –

+0

Non riesce in localhost e quando viene distribuito su GAE. Ma: l'eccezione e il traceback differiscono. Non ho incluso quello locale perché volevo escludere le incompatibilità locali come possibile origine del problema. –

risposta

7

Non ho familiarità con il modulo sys. Per dare una risposta alla domanda, preferisco usare webapp2. Questo è un gestore di lavoro:

import webapp2 
import StringIO 
import numpy as np 
import matplotlib.pyplot as plt 


class MainPage(webapp2.RequestHandler): 
    def get(self): 
     plt.plot(np.random.random((20))) 
     sio = StringIO.StringIO() 
     plt.savefig(sio, format="png") 
     img_b64 = sio.getvalue().encode("base64").strip() 
     plt.clf() 
     sio.close() 
     self.response.write("""<html><body>""") 
     self.response.write("<img src='data:image/png;base64,%s'/>" % img_b64) 
     self.response.write("""</body> </html>""") 

app = webapp2.WSGIApplication([('/', MainPage)], debug=True) 

In alternativa, si potrebbe scrivere il sio.getvalue() nel blobstore con i file API e utilizzare il metodo get_serving_url() di immagini API per evitare di codificare in base64.

+0

grazie per il vostro feedback. il mio problema è che non riesco nemmeno a importare matplotlib. forse la mia configurazione dell'app è il problema? come ti sembra? –

+0

la tua app.yaml sembra buona tranne due cose: hello_world.APP come commentato @peterretief e l'importazione webapp2 nelle 'librerie'. questo script funziona solo in produzione. –

+0

Sono riuscito a farlo funzionare in base al campione, anche se davvero non voglio creare HTML, ma file PNG. Allegherò il mio codice alla mia domanda. –

2

Il problema era che si stavano impostando le variabili di ambiente MATPLOTLIBDATA e MPLCONFIGDIR nella directory dell'app prima di importare matplotlib. Poiché non disponevi di caratteri nella directory dell'app, non è stato possibile caricare alcun carattere.