Streamlit中Session State问题:场上球员信息重复显示
问题解决:Streamlit实时NBA球员阵容重复显示的问题
问题原因
核心差异在于内容渲染方式不同:
- 实时比分用
score_placeholder.info()实现,Streamlit占位符(st.empty())每次调用会替换原有内容,因此保持单行显示。 - 球员信息直接调用
st.markdown(),每次执行该代码都会在页面新增元素,导致阵容变动时不断追加新行。
解决方案
给球员信息创建专属占位符,用占位符的替换逻辑更新内容,而非新增元素。具体修改如下:
- 添加球员信息占位符:在创建其他占位符的位置新增一行:
# 创建比分、球员、DataFrame的占位符 score_placeholder = st.empty() players_placeholder = st.empty() # 新增球员信息占位符 df_placeholder = st.empty() refresh_placeholder = st.empty()
- 修改球员信息更新逻辑:将直接调用
st.markdown()改为用占位符替换内容,同时处理首次加载显示:
# 原有的球员信息判断逻辑内修改 if 'current_players' not in st.session_state: st.session_state.current_players = {} # 先更新占位符内容,确保每次都显示最新阵容 home_display = f'<b>{st.session_state.home_team}</b>: {", ".join(home_players)}' away_display = f'<b>{st.session_state.away_team}</b>: {", ".join(away_players)}' players_placeholder.markdown(f"{home_display}<br>{away_display}", unsafe_allow_html=True) # 仅在阵容变化时更新Session State if st.session_state.current_players.get('home') != home_players or st.session_state.current_players.get('away') != away_players: st.session_state.current_players['home'] = home_players st.session_state.current_players['away'] = away_players
完整修改后的关键代码片段
if 'selected_game_id' in st.session_state: if st.button("View Game Plays"): game_over = is_game_over(st.session_state.selected_game_id) # 创建比分、球员、DataFrame的占位符 score_placeholder = st.empty() players_placeholder = st.empty() # 新增球员占位符 df_placeholder = st.empty() refresh_placeholder = st.empty() def update_display(): columns = [ 'game_id', 'action_number', 'clock', 'timeActual', 'period', 'periodType', 'team_id', 'teamTricode', 'actionType', 'subType', 'descriptor', 'qualifiers', 'personId', 'x', 'y', 'possession', 'scoreHome', 'scoreAway', 'description' ] all_plays = get_all_plays_from_db(st.session_state.selected_game_id) if not game_over: consumer.subscribe(['nba-plays']) start_time = time.time() while time.time() - start_time < 3: json_obj = json.loads(boxscore.BoxScore(game_id=st.session_state.selected_game_id).get_json()) home_players = [player['name'] for player in json_obj['game']['homeTeam']['players'] if player['oncourt'] == '1'] away_players = [player['name'] for player in json_obj['game']['awayTeam']['players'] if player['oncourt'] == '1'] if 'current_players' not in st.session_state: st.session_state.current_players = {} # 更新占位符内容,确保显示最新阵容 home_display = f'<b>{st.session_state.home_team}</b>: {", ".join(home_players)}' away_display = f'<b>{st.session_state.away_team}</b>: {", ".join(away_players)}' players_placeholder.markdown(f"{home_display}<br>{away_display}", unsafe_allow_html=True) # 仅在阵容变化时更新Session State if st.session_state.current_players.get('home') != home_players or st.session_state.current_players.get('away') != away_players: st.session_state.current_players['home'] = home_players st.session_state.current_players['away'] = away_players # Kafka消费逻辑保持不变 msg = consumer.poll(0.1) if msg is None: continue if msg.error(): if msg.error().code() == KafkaError._PARTITION_EOF: continue else: st.error(f"Error: {msg.error()}") break play_data = json.loads(msg.value().decode('utf-8')) if play_data['gameId'] == st.session_state.selected_game_id: play_tuple = tuple(play_data.get(col, None) for col in columns) all_plays.append(play_tuple) # 后续DataFrame和比分更新逻辑保持不变 if all_plays: # ... 原有代码 ...
说明
- 占位符
players_placeholder会在每次update_display执行时,用最新球员信息替换原有内容,避免重复追加。 - 修改后无论阵容是否变动,页面都会显示当前最新场上球员,且不会产生重复行。
内容的提问来源于stack exchange,提问作者Chase P.
相关产品推荐
相关产品推荐

