【问题标题】:How to make a dataframe download through browser using python如何使用python通过浏览器下载数据框
【发布时间】:2021-09-02 06:12:14
【问题描述】:

我有一个函数,它在函数末尾生成一个数据框,我将其导出为 Excel 工作表。 df.to_excel('response.xlsx') 这个 excel 文件被保存在我的工作目录中。 现在我将它作为 web 应用程序托管在 heroku 上的 Streamlit 中,但是一旦调用此函数,我希望将这个 excel 文件下载到用户的本地磁盘(普通浏览器下载)中。有什么办法吗?

【问题讨论】:

标签: python pandas dataframe heroku streamlit


【解决方案1】:

来自streamlit 的Snehan Kekre 在this thread 中编写了以下解决方案。


streamlit as st
import pandas as pd
import io

import base64
import os
import json
import pickle
import uuid
import re


def download_button(object_to_download, download_filename, button_text, pickle_it=False):
    """
    Generates a link to download the given object_to_download.
    Params:
    ------
    object_to_download:  The object to be downloaded.
    download_filename (str): filename and extension of file. e.g. mydata.csv,
    some_txt_output.txt download_link_text (str): Text to display for download
    link.
    button_text (str): Text to display on download button (e.g. 'click here to download file')
    pickle_it (bool): If True, pickle file.
    Returns:
    -------
    (str): the anchor tag to download object_to_download
    Examples:
    --------
    download_link(your_df, 'YOUR_DF.csv', 'Click to download data!')
    download_link(your_str, 'YOUR_STRING.txt', 'Click to download text!')
    """
    if pickle_it:
        try:
            object_to_download = pickle.dumps(object_to_download)
        except pickle.PicklingError as e:
            st.write(e)
            return None

    else:
        if isinstance(object_to_download, bytes):
            pass

        elif isinstance(object_to_download, pd.DataFrame):
            #object_to_download = object_to_download.to_csv(index=False)
            towrite = io.BytesIO()
            object_to_download = object_to_download.to_excel(towrite, encoding='utf-8', index=False, header=True)
            towrite.seek(0)

        # Try JSON encode for everything else
        else:
            object_to_download = json.dumps(object_to_download)

    try:
        # some strings <-> bytes conversions necessary here
        b64 = base64.b64encode(object_to_download.encode()).decode()

    except AttributeError as e:
        b64 = base64.b64encode(towrite.read()).decode()

    button_uuid = str(uuid.uuid4()).replace('-', '')
    button_id = re.sub('\d+', '', button_uuid)

    custom_css = f""" 
        <style>
            #{button_id} {{
                display: inline-flex;
                align-items: center;
                justify-content: center;
                background-color: rgb(255, 255, 255);
                color: rgb(38, 39, 48);
                padding: .25rem .75rem;
                position: relative;
                text-decoration: none;
                border-radius: 4px;
                border-width: 1px;
                border-style: solid;
                border-color: rgb(230, 234, 241);
                border-image: initial;
            }} 
            #{button_id}:hover {{
                border-color: rgb(246, 51, 102);
                color: rgb(246, 51, 102);
            }}
            #{button_id}:active {{
                box-shadow: none;
                background-color: rgb(246, 51, 102);
                color: white;
                }}
        </style> """

    dl_link = custom_css + f'<a download="{download_filename}" id="{button_id}" href="data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,{b64}">{button_text}</a><br></br>'

    return dl_link


vals= ['A','B','C']
df= pd.DataFrame(vals, columns=["Title"])  

filename = 'my-dataframe.xlsx'
download_button_str = download_button(df, filename, f'Click here to download {filename}', pickle_it=False)
st.markdown(download_button_str, unsafe_allow_html=True)

我建议在该论坛上搜索主题。这段代码似乎至少有 3-4 种替代方案。

【讨论】:

    【解决方案2】:

    Mark Madson 在 github 上发布了 this workaround。我从 repo 中取出它并粘贴在这里作为答案。

    import base64
    import pandas as pd
    import streamlit as st
      
    def st_csv_download_button(df):
        csv = df.to_csv(index=False) #if no filename is given, a string is returned
        b64 = base64.b64encode(csv.encode()).decode()
        href = f'<a href="data:file/csv;base64,{b64}">Download CSV File</a>'
        st.markdown(href, unsafe_allow_html=True)  
    
    

    用法:

    st_csv_download_button(my_data_frame)
    

    右击+另存为。

    我认为你可以通过 to_excel 而不是 to_csv 来做到这一点。

    【讨论】:

      猜你喜欢
      • 2018-01-17
      • 1970-01-01
      • 2020-03-07
      • 1970-01-01
      • 2017-09-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多