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

Streamlit中Session State问题:场上球员信息重复显示

问题解决:Streamlit实时NBA球员阵容重复显示的问题

问题原因

核心差异在于内容渲染方式不同:

  • 实时比分用score_placeholder.info()实现,Streamlit占位符(st.empty())每次调用会替换原有内容,因此保持单行显示。
  • 球员信息直接调用st.markdown(),每次执行该代码都会在页面新增元素,导致阵容变动时不断追加新行。

解决方案

给球员信息创建专属占位符,用占位符的替换逻辑更新内容,而非新增元素。具体修改如下:

  1. 添加球员信息占位符:在创建其他占位符的位置新增一行:
# 创建比分、球员、DataFrame的占位符
score_placeholder = st.empty()
players_placeholder = st.empty()  # 新增球员信息占位符
df_placeholder = st.empty()
refresh_placeholder = st.empty()
  1. 修改球员信息更新逻辑:将直接调用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.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 04:58:13