You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 18:30:49