Streamlit启动时按钮on_click函数触发IndexError问题求助
问题分析与解决
问题原因
- 按钮
on_click参数错误:代码中直接写on_click=elaborate_documents(embeddings_type),会导致应用启动时立即执行elaborate_documents函数,而非等待按钮点击。此时st.session_state.pdfs是空列表(st.file_uploader默认返回空列表,而非初始化的None),访问索引0自然触发IndexError。 - 状态类型不匹配:初始化
st.session_state.pdfs为None,但st.file_uploader返回的是列表(空或包含文件对象),导致后续if st.session_state.pdfs == None的判断永远不成立,即使没上传文件也会进入else分支执行st.session_state.pdfs[0]引发错误。 - 点击两次才执行的问题:之前把函数调用移出
on_click后,Streamlit的页面刷新机制会导致第一次点击仅触发页面重载,第二次才执行逻辑,因为函数执行未绑定到按钮点击的状态触发。
解决步骤
1. 修正按钮on_click传参方式
on_click需要传入函数对象,而非函数调用结果。如果要传递参数,用args参数:
# 原错误代码 if st.button("Process the documents", type="primary", on_click=elaborate_documents(embeddings_type)): pass # 修改方式一:用条件分支包裹函数调用 if st.button("Process the documents", type="primary"): elaborate_documents(embeddings_type) # 修改方式二:用on_click+args传递参数 st.button("Process the documents", type="primary", on_click=elaborate_documents, args=(embeddings_type,))
2. 统一st.session_state.pdfs的类型
初始化和上传时都用列表,避免类型混乱:
def main(): embeddings_type = "SentenceTransformer-embeddings" if "pdfs" not in st.session_state: st.session_state.pdfs = [] # 初始化为空列表,而非None with st.sidebar: st.session_state.pdfs = st.file_uploader( "Drag or press Browse files here to upload your documents:", type="pdf", accept_multiple_files=True )
3. 在处理函数中增加空判断
在elaborate_documents里先检查文件列表是否为空,再执行后续逻辑:
def elaborate_documents(embeddings_type): st.session_state.pdf_elaborated_flag = True # 先判断是否有上传文件 if not st.session_state.pdfs: st.write("No document uploaded") return with st.spinner("Training in progress.."): chunks, titles = get_pdf_text(st.session_state.pdfs) st.subheader("Your documents:") store_name = st.session_state.pdfs[0].name[:-4] st.write(f'{titles}') VectorStore = get_text_embedding(store_name, chunks, embeddings_type) st.session_state.conversation = get_conversiont_chain(VectorStore)
4. 解决点击两次才执行的问题
使用按钮点击的条件分支包裹函数调用(即上述修改方式一),这样每次点击按钮时,页面刷新后会立即执行函数逻辑,无需重复点击。
完整修改后关键代码片段
def elaborate_documents(embeddings_type): st.session_state.pdf_elaborated_flag = True if not st.session_state.pdfs: st.write("No document uploaded") return with st.spinner("Training in progress.."): chunks, titles = get_pdf_text(st.session_state.pdfs) st.subheader("Your documents:") store_name = st.session_state.pdfs[0].name[:-4] st.write(f'{titles}') VectorStore = get_text_embedding(store_name, chunks, embeddings_type) st.session_state.conversation = get_conversiont_chain(VectorStore) def main(): embeddings_type = "SentenceTransformer-embeddings" if "pdfs" not in st.session_state: st.session_state.pdfs = [] with st.sidebar: st.session_state.pdfs = st.file_uploader( "Drag or press Browse files here to upload your documents:", type="pdf", accept_multiple_files=True ) if st.button("Process the documents", type="primary"): elaborate_documents(embeddings_type)
内容的提问来源于stack exchange,提问作者fbottarelli
相关产品推荐
相关产品推荐

