如何使用python通过浏览器下载数据框
Posted
技术标签:
【中文标题】如何使用python通过浏览器下载数据框【英文标题】:How to make a dataframe download through browser using python 【发布时间】:2021-09-02 06:12:14 【问题描述】:我有一个函数,它在函数末尾生成一个数据框,我将其导出为 Excel 工作表。
df.to_excel('response.xlsx')
这个 excel 文件被保存在我的工作目录中。
现在我将它作为 web 应用程序托管在 heroku 上的 Streamlit 中,但是一旦调用此函数,我希望将这个 excel 文件下载到用户的本地磁盘(普通浏览器下载)中。有什么办法吗?
【问题讨论】:
截至今天,2021 年 6 月 17 日,还没有正式的下载实现。然而。有这个解决方法:github.com/MarcSkovMadsen/awesome-streamlit/blob/master/gallery/… Streamlit 现在支持原生下载blog.streamlit.io/0-88-0-release-notes 【参考方案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
来做到这一点。
【讨论】:
以上是关于如何使用python通过浏览器下载数据框的主要内容,如果未能解决你的问题,请参考以下文章
selenium+python自动化80-文件下载(不弹询问框)