每当(至少)2个人尝试在我的应用程序中生成轮廓图时,其中至少有一个会收到随机错误,具体取决于第一个人设法绘制的距离..(" unknown element o& #34;," ContourSet必须在当前轴中#34;只是其中两种可能性)
以下是可以产生错误的减少测试,如果您尝试同时在2个或更多选项卡中加载此页面,第一个将正确呈现,而第二个将产生错误。 (我发现这样做最简单的方法是用鼠标中键点击Chrome中的刷新页面按钮几次)
views.py
def home(request):
return render(request, 'home.html', {'chart': _test_chart()})
def _test_chart():
import base64
import cStringIO
import matplotlib
matplotlib.use('agg')
from matplotlib.mlab import bivariate_normal
import matplotlib.pyplot as plt
import numpy as np
from numpy.core.multiarray import arange
delta = 0.5
x = arange(-3.0, 4.001, delta)
y = arange(-4.0, 3.001, delta)
X, Y = np.meshgrid(x, y)
Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
Z = (Z1 - Z2) * 10
fig = plt.figure(figsize=(10, 5))
plt.contour(X, Y, Z, 10, colors='k')
jpg_image_buffer = cStringIO.StringIO()
fig.savefig(jpg_image_buffer)
array = base64.b64encode(jpg_image_buffer.getvalue())
jpg_image_buffer.close()
return array
home.html(只需这一行就够了)
<img src="data:image/png;base64,{{ chart }}" />
我尝试使用mpld3代替处理图像的生成,这仍然会产生不同的错误,所以我知道它绝对不是数字的保存,而是它的生成。我也试过使用ThreadPool
和Threading
无济于事,据我所知,似乎在matplotlib中创建一个轮廓图不能支持多个不会对网站起作用的实例。 ..
我现在能想到的唯一明确的解决方案是将matplotlib替换为我真正不想做的其他事情。
有没有办法用matplotlib生成轮廓图对我有用?
答案 0 :(得分:1)
首先,让我首先说通过在几个线程中调用_test_chart
来更容易重现
from threading import Thread
for i in xrange(2):
Thread(target=_test_chart).start()
执行上述操作后,将根据需要工作,而第二个将崩溃。
这个的简单原因是pyplot模块不是为多线程而设计的,因此这两个图表在他们尝试绘制时会混淆数据。
可以更好地解释这一点... pyplot用于在命令行方便地绘图并保持全局状态。例如,当你说plt.figure()时,它会将数字添加到全局列表中,然后设置&#34;当前数字&#34;指向最近创建的图形的指针。然后随后的绘图命令自动写入该图。显然,这不是线程安全的......
有两种方法可以解决此问题,
for i in xrange(2):
pool = Pool(processes=1)
pool.apply(_test_chart)
虽然这会起作用,但你会发现性能明显下降,因为创建流程通常需要与生成图表一样长(我认为这是不可接受的!)
def _test_chart2():
delta = 0.5
x = arange(-3.0, 4.001, delta)
y = arange(-4.0, 3.001, delta)
X, Y = np.meshgrid(x, y)
Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
Z = (Z1 - Z2) * 10
fig = figure(figsize=(10, 5))
ax1 = fig.add_subplot(111)
extents = [x.min(), x.max(), y.min(), y.max()]
im = ax1.imshow(Z,
interpolation='spline36',
extent=extents,
origin='lower',
aspect='auto',
cmap=cm.jet)
ax1.contour(X, Y, Z, 10, colors='k')
jpg_image_buffer = cStringIO.StringIO()
fig.savefig(jpg_image_buffer)
array = base64.b64encode(jpg_image_buffer.getvalue())
jpg_image_buffer.close()
return array