我一直在使用 Streamlit 进行小型前端项目。以前我提供了一个应用程序将使用的数据文件,但我还希望用户上传他们自己的文件并针对 python 脚本运行它们。

我的目标: 允许用户上传文件并选择运行应用程序的文件,为演示提供默认文件

设置多页

在这种方法中,我决定最好将文件的上传和运行脚本与文件分开到单独的页面中。

文件结构

streamlit_app.py充当主页,包含有关项目的一些信息,以及如何使用它。

pages应用程序页面所在的子目录。

file_picker.py是让用户上传文件的逻辑所在。

main.py是主要的应用程序脚本。

data子目录是保存输入数据的地方,目前只包含我为演示提供的默认数据。

此文件夹结构允许从应用程序的侧面菜单在这些页面之间导航:

侧边菜单导航

文件选择器

Streamlit 提供了一个file_uploader,它可以通过st.file_uploader访问,看起来像这样:

Streamlit 文件选择器

文件选择器的代码,以标题作为参数

给用户更多信息是个好主意,所以我添加了一些文本区域来通知用户当前状态。

我添加了一个小文本区域,最多包含 5 行(最多 5 行,以防用户上传的文件少于 5 行),只是为了向用户显示他们刚刚上传的文件的片段。 (请注意,文本区域是在‘if’语句之后定义的)。

CSV 预览

同样,我添加了一个文本区域来通知用户结果。

显示上传状态的文本区域

最后,我添加了一个按钮和一个上传功能:

单击该按钮时,将运行上传功能,并保存文件。这里我使用了相对路径,所以这个项目以后可以被 dockerised。

这将导致以下file_picker.py:

导入 streamlit 作为 st

导入 os.path

导入 pathlibst.write("""

# 文件选择器

""")uploaded_file u003d st.file_uploader("选择一个 CSV 文件")如果上传的_file 不是 None:

字节_data u003d 上传_file.getvalue()

数据 u003d 上传_file.getvalue().decode('utf-8').splitlines()

st.session_state["preview"] u003d '' for i in range(0, min(5, len(data))):

st.session_state["preview"] +u003d data[i]preview u003d st.text_area("CSV Preview", "", heightu003d150, keyu003d"preview")

upload_state u003d st.text_area("上传状态", "", keyu003d"upload_state")def upload():

如果上传\文件为无:

st.session_state["upload_state"] u003d "先上传文件!"

别的:

数据 u003d 上传_file.getvalue().decode('utf-8')

parent_path u003d pathlib.Path(__file__).parent.parent.resolve()

保存_path u003d os.path.join(父_path,“数据”)

完成\name u003d os.path.join(save_path, 上传\file.name)

目的地\文件u003d打开(完整\名称,“w”)

目的地\file.write(数据)

目的地\file.close()

st.session_state["upload_state"] u003d "已保存" + complete_name + " 成功!"st.button("上传文件到沙盒", on_clicku003dupload)

主文件

用户上传文件后,他们可以从侧面菜单导航到应用程序的main部分。在那里我使用st.selectbox放置了一个下拉菜单。

使用类似的方法,我从data子目录中检索了所有文件名,并将它们用作下拉菜单中的选项:

从“数据”子目录中选择输入文件的逻辑

可以使用data_path变量检索选定的文件位置,如下所示:

选定的文件位置

然后可以将file_location作为参数传递给主脚本。而已!

这导致以下main.py:

导入 streamlit 作为 st

进口我们

导入路径库

从操作系统导入列表目录

从 os.path 导入 isfile,joinst.write("""

# 演示

""")parent_path u003d pathlib.Path(__file__).parent.parent.resolve()

数据_path u003d os.path.join(父_path,“数据”)

onlyfiles u003d [f for f in listdir(data_path) if isfile(join(data_path, f))]option u003d st.sidebar.selectbox('Pick a dataset', onlyfiles)file_locationu003dos. path.join(data_path, option)# 使用 `file_location`作为主脚本的参数

结论

这些是我为允许用户上传文件并使用它运行脚本而采取的步骤。

在这个阶段,没有文件验证,但通常最好确保用户上传的文件是有效的,即:

  • 它具有正确的文件扩展名

  • 文件格式正确

  • 它包含的数据不会破坏你的脚本

我选择不在此处包含此内容,因为验证确实特定于您正在处理的数据类型,并且这是我在此应用程序中的下一步。

我希望这会有所帮助,并且有人觉得这很有用!

升级编码

感谢您成为我们社区的一员!你走之前:

  • 👏 为故事鼓掌,关注作者👉

  • 📰 在 Level Up Coding 出版物中查看更多内容

  • 🔔 关注我们:Twitter|领英|时事通讯

🚀👉加入Level Up人才集体,找到一份了不起的工作

Logo

学AI,认准AI Studio!GPU算力,限时免费领,邀请好友解锁更多惊喜福利 >>>

更多推荐