You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Streamlit启动时按钮on_click函数触发IndexError问题求助

问题分析与解决

问题原因

  1. 按钮on_click参数错误:代码中直接写on_click=elaborate_documents(embeddings_type),会导致应用启动时立即执行elaborate_documents函数,而非等待按钮点击。此时st.session_state.pdfs是空列表(st.file_uploader默认返回空列表,而非初始化的None),访问索引0自然触发IndexError。
  2. 状态类型不匹配:初始化st.session_state.pdfs为None,但st.file_uploader返回的是列表(空或包含文件对象),导致后续if st.session_state.pdfs == None的判断永远不成立,即使没上传文件也会进入else分支执行st.session_state.pdfs[0]引发错误。
  3. 点击两次才执行的问题:之前把函数调用移出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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 07:27:30