【问题标题】:download csv file in Dash在 Dash 中下载 csv 文件
【发布时间】:2020-05-13 20:48:21
【问题描述】:

我正在使用 Dash plotly 构建一个应用程序,该应用程序可以选择保存一个 csv 文件(在应用程序运行期间创建),但我在保存 csv 文件时遇到问题。

我试图做的是使用html.A 组件,并使用此数据设置href 属性:

csv_string = df.to_csv(encoding='utf-8', index=True)
csv_string = "data:text/csv;charset=utf-8," + urllib.parse.quote(csv_string)

csv_string 是我分配给href 属性的数据。 我看到有人推荐这种方法,它似乎确实有效。

数据框太大时出现问题。发生这种情况时,尝试保存文件时出现下载错误。

  1. 您认为我对问题的分类正确吗?真的有可能是尺寸问题吗?

  2. 您认为我可以做些什么来解决这个问题?还有其他保存文件的解决方案吗?我需要说我不想将文件下载到静态文件夹。我需要有解决方案,将文件下载到用户的默认下载文件夹,或者让用户可以选择他想要将文件保存到的文件夹(可能会弹出窗口)。

编辑: 我找到了这个链接:http://chandrewz.github.io/blog/downloading-large-csv-files-via-href,它准确地描述了我遇到的问题。有没有类似于作者在Python中建议的解决方案?

【问题讨论】:

    标签: python pandas csv save plotly-dash


    【解决方案1】:

    dash-extensions 包中的Download 组件使用 Blob 执行下载操作,因此它可能会解决您的问题。这是一个小例子,

    import dash
    import dash_html_components as html
    import numpy as np
    import pandas as pd
    
    from dash.dependencies import Output, Input
    from dash_extensions import Download
    from dash_extensions.snippets import send_data_frame
    
    # Generate some example data.
    data = np.column_stack((np.arange(10), np.arange(10) * 2))
    df = pd.DataFrame(columns=["a column", "another column"], data=data)
    # Create app.
    app = dash.Dash(prevent_initial_callbacks=True)
    app.layout = html.Div([html.Button("Download csv", id="btn"), Download(id="download")])
    
    @app.callback(Output("download", "data"), [Input("btn", "n_clicks")])
    def generate_csv(n_nlicks):
        return send_data_frame(df.to_csv, filename="some_name.csv")
    
    if __name__ == '__main__':
        app.run_server()
    

    如果你决定尝试一下,你可以通过 pip 安装包

    pip install dash-extensions==0.0.18
    

    免责声明:我是 Dash Extensions 的作者。

    编辑:根据 Dash 1.20.0,Download 组件已合并到 dash-core-components。因此,上面的示例可以在不使用任何第三方库的情况下重写,

    import dash
    import dash_html_components as html
    import dash_core_components as dcc
    import numpy as np
    import pandas as pd
    from dash.dependencies import Output, Input
    
    # Generate some example data.
    data = np.column_stack((np.arange(10), np.arange(10) * 2))
    df = pd.DataFrame(columns=["a column", "another column"], data=data)
    # Create app.
    app = dash.Dash(prevent_initial_callbacks=True)
    app.layout = html.Div([html.Button("Download csv", id="btn"), dcc.Download(id="download")])
    
    @app.callback(Output("download", "data"), [Input("btn", "n_clicks")])
    def generate_csv(n_nlicks):
        return dcc.send_data_frame(df.to_csv, filename="some_name.csv")
    
    if __name__ == '__main__':
        app.run_server()
    

    【讨论】:

    • 不错的功能!一个问题,当我将它添加到仪表板应用程序时,默认情况下,按钮在每次回调时都会单击,而不仅仅是在我单击它时,因此下载的文件次数比预期的要多。有解决办法吗?
    • 谢谢!如果您将按钮设置为回调的唯一输入并添加 prevent_initial_callback 标志,则下载应仅在单击按钮时开始。
    【解决方案2】:

    这是我允许使用 Dash 框架下载 CSV 文件的方法,无需额外的库:

    from flask import request, Response
    import dash
    import dash_core_components as dcc
    import dash_html_components as html
    from dash.dependencies import Input, Output
    import pandas as pd
    
    # This is in the Dash app layout
    # Using Bootstrap class for nice styling
    html.A(
        "Download CSV",
        id="download_csv",
        href="#",
        className="btn btn-outline-secondary btn-sm"
    )
    
    
    @app.callback(
        Output('download_csv', 'href'),
        [Input('some_input', 'value')]
    )
    def some_callback(input_value):
        """Some callback that updates the href for the button"""
        
        return f"/download_csv?value={input_value}"
    
    
    @app.route('/download_csv')
    def dash_download_csv():
        """Regular Flask route.
        Download a CSV file from an existing Pandas DataFrame"""
    
        # Here's the argument passed to the URL in the Dash callback
        value = request.args.get('value')
        df = get_df(value)
        
        # Convert DataFrame to CSV
        csv = df.to_csv(index=False)
    
        return Response(
            csv,
            mimetype="text/csv",
            headers={
                "Content-disposition": "attachment; filename=rcom_data.csv"
            }
        )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多