🌀

Streamlitのst.spinnerで長時間の処理を行った際に画面全体がフェードしてしまう現象

2025/04/07に公開

はじめに

Streamlitで生成AIアプリを作成した際に、表題の事象に遭遇しました。いまだに完全にはなぜこれが起こるのか理解できていないですが、解決策は見つかったのでメモしておきます。

環境

Windows
Python 3.12.0
streamlit==1.41.0

現象

import time

import streamlit as st


def render_sidebar():
    with st.sidebar:
        st.text_input("あなたの名前は?", key="name")

def render_main_fade_all():
    if st.session_state.name is not None:
        st.markdown("# Title")
        st.markdown("ここもフェードします。")

        def recommend_dinner():
            with st.spinner("処理中です。"):
                time.sleep(5)
                st.write(
                    f"{st.session_state.name}さんへのおすすめの晩御飯を考えました!"
                )
                st.markdown("- ココ壱番屋\n - 丸亀うどん\n - オリジン弁当")

        st.button("実行", on_click=recommend_dinner)


if __name__ == "__main__":
    render_sidebar()
    render_main_fade_all()

以下のように、st.spinner内での処理実行中に、コードではst.spinnerの外にある部分の描画も中断され、画面全体が白くフェードしてしまいます。

ユーザ観点からすると、フリーズしてしまったかのような印象を受けるため、UI的にも問題になりえます。

解決方法

import time

import streamlit as st


def render_sidebar():
    with st.sidebar:
        st.text_input("あなたの名前は?", key="name")


def render_main():
    if st.session_state.name is not None:
        st.markdown("# Title")
        st.markdown("ここはフェードしないです。")

        if st.button("実行"):
            with st.spinner("処理中です。"):
                time.sleep(5)
                st.write(
                    f"{st.session_state.name}さんへのおすすめの晩御飯を考えました!"
                )
                st.markdown("- ココ壱番屋\n - 丸亀うどん\n - オリジン弁当")

if __name__ == "__main__":
    render_sidebar()
    render_main()

st.spinnerの処理を、st.buttonのon_clickコールバックに含めないようにすることで、画面の一部のみがフェードする挙動となります。

on_clickが実行される際に、画面全体が再描画されるのですが、その途中にst.spinnerが挟まることで、全体が処理中のようにフェードしてしまうということのようですが、背後の仕組みは完全には理解しきれていません。

Discussion