多用户访问时Streamlit应用崩溃的排查方案咨询
调试排查步骤
一、修复代码中的潜在问题
- 补全缺失依赖:代码中使用
locale模块但未导入,必须添加import locale到开头,多用户并发时未导入的模块会引发隐式错误。 - 修正会话ID赋值逻辑:当前只要
memberid不为空就会覆盖session_state['id'],但text_input会保留输入值,导致多用户切换时ID串用。修改为仅点击「Submit」按钮时更新:if st.sidebar.button(label='Submit'): if memberid.strip(): st.session_state['id'] = memberid - 避免全局变量并发冲突:虽然用了缓存,但全局的
active_enrollees和utilization_data在多线程环境下可能出现竞态条件。建议在需要时从缓存函数中获取,或封装到会话相关逻辑里。 - 添加异常与空值处理:
- 获取
policy_start_date等字段时,添加空值判断,避免iat[0]引发索引错误:policy_row = active_enrollees.loc[active_enrollees['MemberNo'] == id] if policy_row.empty: st.write('No data found for the given member number') return policy_start_date = pd.to_datetime(policy_row['Policy Inception'].iat[0]) - 对
locale.format_string添加异常捕获,处理非整数或0值的情况:try: member_pa_value = '#' + locale.format_string('%d', member_pa_value, grouping=True) except: member_pa_value = '#0' - 读取
Benefit_Limits.csv前添加文件存在性检查:import os if not os.path.exists('Benefit_Limits.csv'): st.error('Benefit_Limits.csv file not found') st.stop() limit_df = pd.read_csv('Benefit_Limits.csv')
- 获取
- 修正DataFrame修改逻辑:直接对切片后的
enrollee_benefit_limit使用inplace=True会引发SettingWithCopyWarning,建议先复制:enrollee_benefit_limit = limit_df.loc[ (limit_df['ClientName'] == client) & (limit_df['ClassName'] == plan) ].copy()
二、开启详细日志定位错误
- 本地模拟多用户测试:用
streamlit run app.py --server.headless true启动应用,同时打开多个浏览器窗口访问,查看终端输出的错误日志,这是最快定位问题的方式。 - Streamlit Cloud日志:进入应用的「Manage app」→「Logs」页面,查看崩溃时的完整错误栈,云环境的日志会记录代码抛出的异常信息。
三、排查资源限制问题
- 数据库连接限制:多用户并发时可能超出SQL Server的连接配额。可以在
get_data_from_sql中确认连接已关闭,或改用连接池(如sqlalchemy的连接池)优化连接管理。 - 内存占用过高:如果
utilization_data数据量过大,多用户并发时内存占用会触发崩溃。可以:- 优化SQL查询,只拉取需要的字段,减少返回的数据量。
- 对大DataFrame的查询操作进行分块处理,避免一次性加载全量数据。
- Streamlit Cloud配额:免费版/基础版有内存和CPU限制,进入应用的「Metrics」页面查看内存、CPU使用情况,确认是否达到配额上限。
四、强化会话隔离
确保所有用户特定状态都通过st.session_state管理,避免全局变量存储用户输入:
# 从session_state读取默认值,保持会话独立性 memberid = st.sidebar.text_input('Enrollee Member ID', value=st.session_state.get('id', ''))
内容的提问来源于stack exchange,提问作者Ademola Atolagbe
相关产品推荐
相关产品推荐

