11

我的标签和标题很清楚地说明了我的问题。我想使用 matplotlib 在 Google App Engine 中创建实时绘图。我已经阅读了文档并在 SO 和 Google 上进行了搜索。我找到了一个帖子,指向这个工作演示。但是当我自己尝试时,它对我不起作用。

我创建了一个简单的应用程序,仅包含一个处理程序脚本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())

和一个配置文件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"

我想绘制一些东西,然后将内容作为 png-image 返回。这个过程适用于像 Apache 或 IIS 这样的普通 Web 服务器,我这样做了一百万次。

问题是:当我在开发服务器中本地运行我的脚本时,我收到一个错误,这可能是由于我的 MPL 版本 1.1.1,这在 GAE 中只是“实验性的”。但是当我将我的应用程序部署到 GAE 时,我得到了一个完全不同的、不相关的错误。

看样子,回溯是:

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

它似乎必须对 MPL 的字体缓存做些什么。我在文档中读到缓存和文件访问是 GAE 中 MPL 的问题之一,但显然,导入对其他人有效。

我究竟做错了什么?

编辑 根据下面的答案,我将代码更改为

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)

就像这样,它正在工作。

4

2 回答 2

7

我不熟悉 sys 模块。为了回答我更喜欢使用 webapp2 的问题。这是一个工作处理程序:

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)

sio.getvalue()或者,您可以使用 files api 在 blobstore 中编写,并使用get_serving_url()images api 的方法来避免在 base64 中编码。

于 2013-01-22T16:23:58.700 回答
2

问题是您在导入 matplotlib 之前将环境变量MATPLOTLIBDATA和环境变量设置为您的应用程序目录。MPLCONFIGDIR由于您的应用程序目录中没有任何字体,因此无法加载任何字体。

于 2013-01-28T22:58:05.830 回答