今天是端午節, 早上忙完祖堂的拜拜後繼續來測試 Streamlit, 本篇旨在測試 Streamlit 的兩個狀態顯示元件的函式 : 進度條元件 st.progress() 與等候元件 st.spinner().
1. 進度條元件 st.progress :
呼叫 st.progress() 函式會建立一個進度條元件, 其參數結構如下 :
st.progress(value=0, text=None, key=None)
st.progress() 的傳回值為一個 Progress 類別的物件, 我們可以在迴圈中利用其 progress() 方法動態更新進度條的值 (0~100 或 0.0~1.0).
參數說明如下表 :
| st.progress() 參數 | 說明 |
|---|---|
| value | 必要參數 (預設 0),進度條的進度,整數 (0~100) 或浮點數(0.0~1.0)。 |
| text | 顯示在進度條下方的文字,支援 Markdown 語法與 emoji 表情。 |
| key | 為此進度條元件指定唯一鍵值以避免重複。 |
# st-progress-test-1-1.py
import streamlit as st
import time
st.subheader('進度條 st.progress()')
progress_bar=st.progress(0, text='任務處理中 ...')
for i in range(100):
progress_bar.progress(i, text=f'目前進度:{i}%') # 更新進度條數值與文字
time.sleep(0.05) # 模擬延遲
st.success("✅ 處理完成!")
此例先呼叫 st.progress() 並設定進度初始值為 0, 然後用迴圈與 time.sleep() 模擬處理所需的延遲時間, 在迴圈中呼叫 st.progress() 來更新進度條的值, 結果如下 :
可見進度條上的初始文字訊息 '任務處理中 ...' 一瞬即逝幾乎無作用; 其次, 雖然迴圈從 0~99 剛好 100 圈, 但任務完成時進度顯示會停在 99%, 這會讓使用者誤以為任務還有 1% 未完成, 因此可將上面程式修改為如下較理想的做法 :
測試 1-2 : 較理想的進度條 [看原始碼]
# st-progress-test-1-2.py
import streamlit as st
import time
st.subheader('進度條 st.progress()')
progress_bar=st.progress(0, text='任務處理中 ...')
for i in range(100):
progress_bar.progress(i, text=f'目前進度:{i}%') # 更新進度條數值與文字
time.sleep(0.05) # 模擬延遲
progress_bar.progress(100, text=f'目前進度:100%')
st.success("✅ 處理完成!")
此例在迴圈結束後再次呼叫 st.progress() 讓進度條之值停在 100, 文字顯示 100%, 這樣使用者就不會誤解任務還有 1% 未完成了, 結果如下 :
或者也可以讓迴圈內從 1% 開始跑到 100% (因為 0% 已在迴圈外初始時跑過了), 這樣就不用在迴圈結束後設定值為 100 了 :
progress_bar.progress(i + 1, text=f'目前進度:{i + 1}%') # 更新進度條數值與文字
下面是較進階的範例, 加入了一個可取消任務的按鈕 :
測試 1-3 : 可取消任務的進度條 [看原始碼]
# st-progress-test-1-3.py
import streamlit as st
import time
st.subheader('進度條 st.progress()')
progress_bar=st.progress(0, text='任務處理中 ...')
st.button("❌ 取消任務", key='cancel')
for i in range(100):
if st.session_state['cancel']: # if st.session_state.cancel: 亦可
progress_bar.progress(0, text='任務取消')
st.warning('⚠️ 任務已取消')
break
progress_bar.progress(i + 1, text=f'目前進度:{i + 1}%') # 更新進度條數值與文字
time.sleep(0.05) # 模擬延遲
if not st.session_state['cancel']:
st.success("✅ 處理完成!")
此例我們在取消任務的按鈕中用 key 參數指定唯一鍵 cancel, 這樣就會在 st.session_state 字典中以 cancel 為鍵追蹤此按鈕的值 (按鈕有被按下過傳回 True, 否則預設為 False), 我們可以利用此字典取得按鈕的即時狀態, 當它被按下時中斷任務跳出迴圈重設進度條 :
如果不中斷任務讓進度條跑完結果如下 :
2. 旋轉等待元件 st.spinner() :
呼叫 st.spinner() 函式並傳入必要參數 text 會建立一個旋轉等待動畫元件, 其參數結構如下 :
st.spinner(text)
必要參數 text 為顯示在旋轉等待動畫後面的提示文字, 例如 '請耐心等待' 或 '任務執行中' 等, st.camera_input() 的傳回值為一個用來顯示旋轉中的 loading 指示器的上下文管理器 contextlib._GeneratorContextManager 物件, 傳回值本身並無實際用途.
st.spinner() 必須搭配 with 語法使用, 例如 :
測試 2-1 : 模擬的旋轉等候元件 [看原始碼]
# st-spinner-test-1.py
import streamlit as st
import time
st.subheader('旋轉等待元件 st.spinner()')
with st.spinner('任務執行中, 請耐心等待'):
time.sleep(15)
st.success("✅ 處理完成!")
此例使用 time.sleep() 模擬處理延遲, 結果如下 :
可見在等待期間會有一個小圓圈動畫持續旋轉, 迴圈結束後整個等待元件會消失.
下面則是以檔案上傳為例使用 st.spinner() 顯示等候訊息的範例 :
測試 2-2 : 檔案上傳時用旋轉等候元件顯示等待訊息 [看原始碼]
# st-spinner-test-2.py
import streamlit as st
import time
st.subheader('用旋轉等待元件 st.spinner() 顯示等候訊息')
uploaded_file=st.file_uploader('請上傳 MP4 影片', type=['mp4'])
if uploaded_file: # 檔案上傳完成
st.write(f'📄 檔案名稱:**{uploaded_file.name}**')
with st.spinner('處理中請耐心等候 ... '): # 等候資料處理
time.sleep(5) # 這裡可以處理存檔, 轉檔, 解碼等耗時工作
st.success('✅ 影片上傳成功, 請按 Play 播放.')
st.video(uploaded_file)
else: # 尚未選取檔案時顯示提示, 並停止執行等待上傳
st.info('請上傳一個 MP4 檔案') # 尚未上傳則提示
st.stop() # 停止 rerun 等待使用者選取檔案後再繼續執行程式
此例使用 if else 判斷檔案是否上傳完成, 選取檔案後會立即上傳, 完成後 uploaded_file 會傳回物件, 沒有選取檔案或上傳中會傳回 None, 這時會顯示 st.info() 的提示訊息並以 st.stop() 停止 rerun 動作. 上傳完成則用 st.spinner() 顯示等候資料處理任務 (例如存檔等) 完成之訊息, 此處使用 time.sleep() 來模擬, 結果如下 :
點選檔案上傳 :
上傳完成後顯示等候訊息 :
處理完畢顯示播放元件 :
由此例可知, st.spinner() 只是用來表示 "後續處理中" 的視覺提示而已, 與上傳進度本身無關.



















































