我有两个链接的“烧瓶应用程序”,每个链接映射到不同的matplotlib可视化,例如:localhost:5000 / line_chart和localhost:5000 / bar_chart。
当我启动服务器,然后单击一条路线(其中任何一条)时,我看到了我的期望。
本地主机:5000 / bar_chart
当我返回查看另一个链接时,两个图都会中断。
本地主机:5000 / line_chart
本地主机:5000 / bar_chart
我每次都可以通过关闭服务器然后再次运行“run.py”脚本来重现这一点。似乎是与内存缓冲区的覆盖冲突。有没有人以前有这个问题?
应用程序/ views.py
import matplotlib
matplotlib.use('Agg') # this allows PNG plotting
import matplotlib.pyplot as plt
import base64
from flask import render_template
from app import app
from io import BytesIO
@app.route('/')
@app.route('/index')
def index():
res = ''
navigation = [['Line Chart','line_chart'],['Bar Chart','bar_chart']]
res = res + '<h1>Matplotlib Chart Examples</h1>'
res = res + '<ul>'
for item in navigation:
name = item[0]
link = item[1]
res = res + '<li><a href="' + link + '">'+ name +'</a></li>'
res = res +'</ul>'
return res
@app.route('/bar_chart')
def bar_chart():
movies = ["Annie Hall", "Ben-Hur", "Casablanca", "Gandhi", "West Side Story"]
num_oscars = [5, 11, 3, 8, 10]
# bars are by default width 0.8, so we'll add 0.1 to the left coordinates
# so that each bar is centered
xs = [i + 0.1 for i, _ in enumerate(movies)]
# plot bars with left x-coordinates [xs], heights [num_oscars]
plt.bar(xs, num_oscars)
plt.ylabel("# of Academy Awards")
plt.title("My Favorite Movies")
# label x-axis with movie names at bar centers
plt.xticks([i + 0.5 for i, _ in enumerate(movies)], movies)
return compute(plt)
@app.route('/line_chart')
def line_chart():
years = [1950, 1960, 1970, 1980, 1990, 2000, 2010]
gdp = [300.2, 543.3, 1075.9, 2862.5, 5979.6, 10289.7, 14958.3]
# create a line chart, years on x-axis, gdp on y-axis
plt.plot(years, gdp, color='green', marker='o', linestyle='solid')
# add a title
plt.title("Nominal GDP")
# add a label to the y-axis
plt.ylabel("Billions of $")
return compute(plt)
def compute(plt):
# run plt.plot, plt.title, etc.
figfile = BytesIO()
plt.savefig(figfile, format='png')
figfile.seek(0) # rewind to beginning of file
#figfile.getvalue() extracts string (stream of bytes)
figdata_png = base64.b64encode(figfile.getvalue())
return render_template('index.html',
title='matplotlib chart',
results=figdata_png)
感谢您的时间。
答案 0 :(得分:2)
我猜你需要两个数字,测试这段代码并告诉发生了什么:
@app.route('/bar_chart')
def bar_chart():
movies = ["Annie Hall", "Ben-Hur", "Casablanca", "Gandhi", "West Side Story"]
num_oscars = [5, 11, 3, 8, 10]
# bars are by default width 0.8, so we'll add 0.1 to the left coordinates
# so that each bar is centered
xs = [i + 0.1 for i, _ in enumerate(movies)]
# plot bars with left x-coordinates [xs], heights [num_oscars]
plt.figure(1)
plt.bar(xs, num_oscars)
plt.ylabel("# of Academy Awards")
plt.title("My Favorite Movies")
# label x-axis with movie names at bar centers
plt.xticks([i + 0.5 for i, _ in enumerate(movies)], movies)
return compute(plt, 1)
@app.route('/line_chart')
def line_chart():
years = [1950, 1960, 1970, 1980, 1990, 2000, 2010]
gdp = [300.2, 543.3, 1075.9, 2862.5, 5979.6, 10289.7, 14958.3]
# create a line chart, years on x-axis, gdp on y-axis
plt.figure(2)
plt.plot(years, gdp, color='green', marker='o', linestyle='solid')
# add a title
plt.title("Nominal GDP")
# add a label to the y-axis
plt.ylabel("Billions of $")
return compute(plt,2)
def compute(plt, fignum):
# run plt.plot, plt.title, etc.
plt.figure(fignum)
figfile = BytesIO()
plt.savefig(figfile, format='png')
figfile.seek(0) # rewind to beginning of file
#figfile.getvalue() extracts string (stream of bytes)
figdata_png = base64.b64encode(figfile.getvalue())
return render_template('index.html',
title='matplotlib chart',
results=figdata_png)
答案 1 :(得分:0)
就我而言,该解决方案无效。尝试访问情节时似乎存在竞争条件。我首先尝试使用库中的锁,但是那没有用,所以我设计了一种锁。就我而言,我想在同一视图上使用相同的功能创建n
图像,因此我首先以以下方式创建列表:
queue = [False for i in range(n)]
然后,我的烧瓶应用程序看起来像这样:
@app.route('/vis/<j>')
def vis(j):
global queue
# We check that it's image's #j turn, as if it was single threaded
j = int(j)
if j == 0:
for i in range(len(queue)):
queue[i] = False
else:
while not queue[j-1]:
# If it's not, we sleep for a short time (from time import sleep)
sleep(0.5)
# This is not important, it's how I was plotting some random figures
# (from random import seed) (from datetime import datetime)
seed(datetime.now())
n = 10
p1 = [randint(0, 10) for _ in range(n)]
p2 = [randint(0, 10) for _ in range(n)]
t = [i for i in range(n)]
fig = plt.figure(j)
plt.clf()
plt.plot(t, p1, color='blue')
plt.plot(t, p2, color='orange')
plt.xlabel('Time')
plt.ylabel('Value')
# Save the plot
img = BytesIO()
fig.savefig(img, dpi=128)
img.seek(0)
# We finished using everything related to plot, so we free the "lock"
queue[j] = True
# Return the object as a file that can be accessed
return send_file(img, mimetype='image/png')
最后,当要在我的烧瓶应用程序中显示此内容时,我要做的就是在HTML文件中使用此<img src="/vis/1">
。
编辑:我忘记了最重要的部分之一!由于某些原因,这仍然会产生一些不相关的线程问题。我抬起头来,那是我提供完整解决方案的时候。通过在文件的开头添加来解决线程问题:
import matplotlib
import matplotlib.pyplot as plt
matplotlib.use('Agg')
由于某种原因,使用那个Agg
后端解决了我所拥有的第二个线程。我对此没有很好的解释,但是它确实起作用,所以对我来说足够了。
或者,也可以通过添加以下内容来运行应用程序以禁用线程:
if __name__ == '__main__':
app.run(threading=False, debug=True)
但是,我目前不知道这是否可以在生产中使用,因此我更喜欢其他解决方案。 :)
如果您遇到同样的问题,希望对您有所帮助!