Flask项目中Matplotlib生成折线图无法保存至static目录问题求助
Flask中Matplotlib图表无法生成图片的解决方案
问题背景
我想要创建一个Python Flask网站,包含柱状图、折线图和时间轴三个页面。现有包含Year、Exports、Imports字段的CSV数据:
1952,8645,8284 1953,9472,8186 1954,11266,9887 1955,13149,12512 1956,15779,14298
已实现datas.py读取CSV并展示数据表格:
from flask import Blueprint, current_app, render_template import os import csv datas = Blueprint('datas', __name__) def read_csv(): data = [] path = os.path.join( current_app.root_path, os.pardir, 'scraping', 'exports-imports.csv' ) try: with open(path, 'r') as f: reader = csv.reader(f) for row in reader: data.append(row) except FileNotFoundError: return "Error: CSV file was not found" return data @datas.route('/datas') def show_data(): try: data = read_csv() return render_template('datas.html', data=data) except IOError: return "The file doesn't exist"
尝试复用read_csv()生成折线图的graphs.py代码:
from flask import Blueprint, render_template import matplotlib.pyplot as plt from .datas import read_csv graphs = Blueprint('graphs', __name__) @graphs.route('/line-chart') def show_line_chart(): data = read_csv() years = [row[0] for row in data] exports = [row[1] for row in data] imports = [row[2] for row in data] plt.plot(years, exports, label="Exports") plt.plot(years, imports, label="Imports") plt.xlabel('Year') plt.ylabel('Value') plt.title('Foreign Trade') plt.legend() plt.tight_layout() plt.savefig('static/line-chart.png') return render_template('line-chart.html')
对应的line-chart.html模板:
{% extends "base.html" %} {% block title %}Line Chart{% endblock %} {% block content %} <div class="container mt-4"> <h1 class="text-center mb-4">Foreign Trade</h1> <img src="{{ url_for('static', filename='line-chart.png') }}" alt="Line Chart"> </div> {% endblock %}
当前问题:运行后项目中未生成任何图片文件,无法在页面展示折线图。
解决步骤
1. 修正静态文件路径
plt.savefig('static/line-chart.png')使用相对路径可能因Flask工作目录不符导致文件生成到错误位置。改用Flask根路径构建绝对路径:
from flask import current_app import os # 替换原savefig代码 img_path = os.path.join(current_app.root_path, 'static', 'line-chart.png') plt.savefig(img_path)
2. 设置Matplotlib非交互式后端
服务器环境下需禁用Matplotlib的交互式后端,避免无法生成图片:
# 在导入matplotlib前添加 import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt
3. 清理绘图资源
每次生成图表后关闭绘图对象,释放内存并避免后续绘图冲突:
plt.savefig(img_path) plt.close() # 必须添加,否则可能导致资源占用或绘图失败
4. 转换数据为数值类型
read_csv()返回的是字符串列表,Matplotlib绘图需要数值类型,需转换出口/进口额:
years = [row[0] for row in data] # 将字符串转为整数 exports = [int(row[1]) for row in data] imports = [int(row[2]) for row in data]
5. 验证数据有效性
添加判断确保read_csv()返回的是有效数据列表,而非错误字符串:
data = read_csv() if isinstance(data, str): return data # 返回CSV读取错误信息
6. 检查文件夹权限
确保Flask进程拥有static文件夹的写入权限:
- Linux/macOS执行:
chmod 755 static - Windows右键文件夹→属性→安全→设置写入权限
7. 添加异常捕获排查错误
在视图函数中捕获所有异常,快速定位问题:
@graphs.route('/line-chart') def show_line_chart(): try: data = read_csv() if isinstance(data, str): return data years = [row[0] for row in data] exports = [int(row[1]) for row in data] imports = [int(row[2]) for row in data] plt.plot(years, exports, label="Exports") plt.plot(years, imports, label="Imports") plt.xlabel('Year') plt.ylabel('Value') plt.title('Foreign Trade') plt.legend() plt.tight_layout() img_path = os.path.join(current_app.root_path, 'static', 'line-chart.png') plt.savefig(img_path) plt.close() return render_template('line-chart.html') except Exception as e: return f"生成图表出错: {str(e)}"
内容的提问来源于stack exchange,提问作者Rajan Rokaya
相关产品推荐
相关产品推荐

