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

如何为Python Shiny应用服务器端生成的图表添加可用下载按钮?

解决Python Shiny中Matplotlib图表的PNG下载问题

你遇到的空文件问题,核心原因是downloadData函数没有生成有效的PNG二进制数据。下面提供两种可行的解决方案:

方法一:复用已渲染的图表对象

通过把已生成的图表对象存储到响应式变量中,在下载时直接复用,避免重复生成数据和图表:

修改步骤:

  1. 导入io模块处理字节流,导入reactive模块创建响应式变量
  2. 在server函数内定义响应式变量存储图表对象
  3. 更新绘图函数,将生成的图表对象存入响应式变量
  4. 完善下载函数,从响应式变量取出图表并生成PNG字节数据

方法二:在下载函数中重新生成图表

如果不想依赖已渲染的对象,可以直接在下载函数里重新生成图表,逻辑更独立:

修改步骤:

  1. 导入io模块
  2. 在downloadData函数内重新生成数据和图表,然后将图表保存到字节流并输出

完整可运行代码(方法一)

from datetime import date
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from shiny import App, Inputs, Outputs, Session, ui, render, reactive
import io  # 用于处理字节流

app_ui = ui.page_fluid(
    ui.output_plot('testvis'),
    ui.download_button("downloadData", "Download"),
)


def server(input: Inputs, output: Outputs, session: Session):
    # 用响应式变量存储生成的图表Axes对象
    plot_obj = reactive.Value[plt.Axes | None](None)

    @output
    @render.plot
    def testvis():
        data = {'x': [1, 2, 3, 4, 5],
                'y': [2, 4, 6, 8, 10]}
        
        df = pd.DataFrame(data)
        plot = df.plot(x='x', y='y', marker='o', linestyle='-', color='b')
        plot_obj.set(plot)  # 将图表对象存入变量
        return plot

    @session.download(
        filename=lambda: f"testdownload-{date.today().isoformat()}-{np.random.randint(100,999)}.png"
    )
    def downloadData():
        ax = plot_obj.get()
        if ax:
            # 创建字节流对象,保存图表为PNG格式
            buf = io.BytesIO()
            ax.figure.savefig(buf, format='png', dpi=100)  # dpi可调整图片清晰度
            buf.seek(0)  # 回到字节流起始位置,确保读取完整数据
            yield buf.getvalue()
            plt.close(ax.figure)  # 关闭图表释放内存
        else:
            yield b''


app = App(app_ui, server)

关键注意点:

  • 必须使用ax.figure.savefig()而非plt.savefig(),因为df.plot()返回的是Axes对象,需要获取其对应的Figure实例
  • 生成字节流后一定要执行buf.seek(0),否则会从流的末尾读取,导致输出空数据
  • 可选关闭Figure对象,避免长时间运行后内存泄漏

内容的提问来源于stack exchange,提问作者hn2112

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 18:05:31