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

如何在Python Shiny模块中生成独立的下载按钮

Python Shiny模块下载按钮被覆盖的解决方法

问题描述

开发Python Shiny应用时,通过模块复用图表、计算逻辑,图表和数据处理功能正常,但所有模块的下载按钮都会下载最后一个模块的数据——比如调用foo和bar两个模块实例,两个按钮都会下载bar.csv;调换模块调用顺序后,则都会下载foo.csv。

最小复现代码:

from shiny import App, module, render, ui


@module.ui
def example_ui():
    return ui.output_ui("download_button")


@module.server
def example_server(
    input,
    output,
    session,
    label,
):
    @render.download(filename="{}.csv".format(label))
    def download_data():
        yield label

    @output
    @render.ui
    def download_button():
        return (ui.download_button("download_data", "Download {}".format(label)),)


app_ui = ui.page_fluid(
    example_ui("foo"),
    example_ui("bar"),
)


def server(input, output, session):
    example_server("foo", "foo")
    example_server("bar", "bar")


app = App(app_ui, server)

问题原因

直接使用@render.download装饰器定义下载函数时,该函数的注册没有与模块的命名空间完全绑定。后续模块实例的同名下载函数会覆盖之前的注册项,导致所有按钮都指向最后一次注册的下载逻辑。

解决方法

改用session.download_handler注册下载逻辑,确保每个模块实例的下载处理函数被隔离在自身的命名空间内:

from shiny import App, module, render, ui

@module.ui
def example_ui():
    return ui.output_ui("download_button")

@module.server
def example_server(
    input,
    output,
    session,
    label,
):
    # 定义下载逻辑函数
    def download_data():
        yield label
    
    # 通过session.download_handler绑定到模块命名空间
    session.download_handler(
        id="download_data",
        filename=lambda: f"{label}.csv",
        handler=download_data
    )

    @output
    @render.ui
    def download_button():
        return ui.download_button("download_data", f"Download {label}")

app_ui = ui.page_fluid(
    example_ui("foo"),
    example_ui("bar"),
)

def server(input, output, session):
    example_server("foo", "foo")
    example_server("bar", "bar")

app = App(app_ui, server)

关键修正说明

  • 使用session.download_handler替代@render.download:将下载逻辑注册到当前模块实例的session命名空间,每个模块的下载处理会被独立隔离,不会互相覆盖。
  • 用lambda动态生成文件名:确保每个模块实例的文件名能正确获取对应的label参数值,避免静态字符串导致的文件名复用问题。
  • 保持下载按钮的ID引用:按钮引用的download_data是模块内的ID,会自动关联到当前模块实例的下载处理函数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 23:31:16