Streamlit应用:文件夹按钮加载数据后聊天窗口消失问题
问题:Streamlit聊天机器人文件夹加载后聊天窗口消失
问题描述
开发基于文件构建的Streamlit聊天机器人应用,支持两种文件上传方式:拖拽上传框与侧边栏的“Use Data from folder”按钮。拖拽上传功能正常,但使用文件夹按钮加载数据后,聊天窗口仅首次显示,在聊天框输入问题并点击发送后,聊天窗口会莫名消失。
核心原因
- Streamlit按钮状态特性:按钮
use_example_file仅在点击瞬间返回True,页面重新渲染(如发送消息触发重跑)时会自动变回False,导致handle_upload函数重新执行时进入拖拽上传分支,uploaded_file变为None,聊天窗口的逻辑分支(if uploaded_file:)不再执行,窗口消失。 - 文件对象未持久化:通过
open("example.csv", "rb")创建的文件对象未存入会话状态,页面重跑时无法复用,按钮状态重置后该分支不会再被触发。
解决方案
1. 用会话状态持久化示例文件状态
修改主应用中的按钮逻辑,将按钮状态和加载的文件对象存入st.session_state,确保页面重跑时状态不丢失:
# 初始化会话状态 if "use_example_file" not in st.session_state: st.session_state["use_example_file"] = False if "example_uploaded_file" not in st.session_state: st.session_state["example_uploaded_file"] = None # 按钮点击时切换状态并加载/释放文件 if st.sidebar.button("Use Data from folder"): st.session_state["use_example_file"] = not st.session_state["use_example_file"] if st.session_state["use_example_file"]: st.session_state["example_uploaded_file"] = open("example.csv", "rb") else: # 关闭文件避免资源占用 if st.session_state["example_uploaded_file"]: st.session_state["example_uploaded_file"].close() st.session_state["example_uploaded_file"] = None # 确定最终的uploaded_file if st.session_state["use_example_file"]: uploaded_file = st.session_state["example_uploaded_file"] else: uploaded_file = utils.handle_upload(["pdf", "txt", "csv"])
2. 调整handle_upload函数
移除原函数中对use_example_file的处理,让它专注处理拖拽上传场景:
@staticmethod def handle_upload(file_types): """ Handles and display uploaded_file :param file_types: List of accepted file types, e.g., ["csv", "pdf", "txt"] """ uploaded_file = st.sidebar.file_uploader("upload", type=file_types, label_visibility="collapsed") if uploaded_file is not None: def show_csv_file(uploaded_file): file_container = st.expander("Your CSV file :") uploaded_file.seek(0) shows = pd.read_csv(uploaded_file) file_container.write(shows) def show_pdf_file(uploaded_file): file_container = st.expander("Your PDF file :") with pdfplumber.open(uploaded_file) as pdf: pdf_text = "" for page in pdf.pages: pdf_text += page.extract_text() + "\n\n" file_container.write(pdf_text) def show_txt_file(uploaded_file): file_container = st.expander("Your TXT file:") uploaded_file.seek(0) content = uploaded_file.read().decode("utf-8") file_container.write(content) def get_file_extension(uploaded_file): return os.path.splitext(uploaded_file.name)[1].lower() file_extension = get_file_extension(uploaded_file.name) if file_extension == ".csv": show_csv_file(uploaded_file) elif file_extension == ".pdf": show_pdf_file(uploaded_file) elif file_extension == ".txt": show_txt_file(uploaded_file) else: st.session_state["reset_chat"] = True return uploaded_file
3. 重置文件指针确保复用
示例文件对象在页面重跑时可能处于文件末尾,使用前需重置指针,可在setup_chatbot函数或文件处理逻辑开头添加:
if uploaded_file: uploaded_file.seek(0) # 后续文件处理逻辑
关键逻辑说明
Streamlit每次交互都会触发整个脚本重新执行,所有局部变量都会重置,只有st.session_state中的数据会保留。通过将示例文件的状态和文件对象存入会话状态,能确保发送消息触发页面重跑时,uploaded_file不会变为None,聊天窗口的逻辑分支能持续执行。
内容的提问来源于stack exchange,提问作者illuminato
相关产品推荐
相关产品推荐

