2025年5月31日 星期六

Streamlit 學習筆記 : 狀態顯示元件

今天是端午節, 早上忙完祖堂的拜拜後繼續來測試 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  為此進度條元件指定唯一鍵值以避免重複。



例如 : 


測試 1-1 : 直覺但不太理想的進度條 [看原始碼]   

# 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() 只是用來表示 "後續處理中" 的視覺提示而已, 與上傳進度本身無關. 

2025年5月30日 星期五

Streamlit 學習筆記 : 訊息框元件

這一周在忙著看 Hahow 企業版的 RAG 教學課程, 今天是端午節補假, 炎炎的夏日午後繼續上週的 Streamlit 測試, 本篇要來測試 Streamlit 的 5 種訊息框元件, 其函式與說明如下表 : 


訊息框函式 說明
st.info(body, icon=None) 顯示資訊訊息框,常用於顯示提示或說明文字。
body: 要顯示的文字內容
icon: 可選圖示 (例如 "ℹ️")
st.success(body, icon=None) 顯示成功訊息框,常用於顯示操作成功的回饋。
body: 要顯示的文字內容
icon: 可選圖示 (例如 "✅")
st.warning(body, icon=None) 顯示警告訊息框,提醒使用者注意潛在風險。
body: 要顯示的文字內容
icon: 可選圖示 (例如 "⚠️")
st.error(body, icon=None) 顯示錯誤訊息框,通常用於錯誤或失敗的狀況。
body: 要顯示的文字內容
icon: 可選圖示 (例如 "❌")
st.exception(exc) 顯示例外訊息框,用於顯示 Python 的例外物件及其 traceback。
exc: 要顯示的例外物件 (如 ValueError)


注意, 這五個元件只是單純輸出顯示, 並非互動式元件, 傳回值均為 None.

本系列所有測試文章參考 :



1. 提示訊息框 st.info() : 

呼叫 st.info() 函式並傳入必要參數 body (要顯示的文字內容) 會建立一個提示訊息框, 其參數結構如下 : 

st.info(body, icon=None)

st.info() 的傳回值為 None. 參數 body 為要輸出的提示文字, icon 參數用來指定顯示於提示文字左側的一個 Unicode 編碼的圖示字元, 通常會使用其中的 emoji 表情圖示區段 (U+1F600 ~ U+1F64F), 因為這區段的 Unicode 編碼在大部分的作業系統中會以彩色字型 (color font) 來著色, 從而讓訊息在視覺上更具辨識度或風格. 

常用的 emoji 圖示如下表 : 


Emoji 圖示 用途說明
ℹ️提示資訊(info)
成功、通過
錯誤、失敗
⚠️警告、注意
🔥異常、關鍵錯誤(exception)
🚀啟動、部署
💡提示、靈感
🔔通知、提醒
🐞錯誤追蹤(bug)
🧠想法、學習
🔒安全、隱私
📅日期、排程


更多 emoji 參考 : 


注意, Streamlit 的五種訊息框函式只有 st.exception() 沒有 icon 參數 (因為此元件用來輸出除錯訊息給開發人員而非用戶, 不需要表情圖示).

例如 :


測試 1 : 用 st.info() 顯示提示訊息 [看原始碼]   

# st-info-test-1.py
import streamlit as st

st.subheader('提示 (info) 訊息框')
st.info('這是預設的提示訊息框')
st.info('這是有 emoji 的提示訊息框', icon="ℹ️")

此例第一個 st.info() 未傳入 icon 參數, 預設僅顯示提示文字; 第二個則傳入表情圖示 ℹ️, 結果如下 :




可見 st.info() 會以淡藍色做為背景色. 

注意, emoji 字元並非在每一種程式編輯器都能正常顯示, 例如 Thonny 預設字型為 Consolas, 如果直接複製貼上 emoji 字型 ℹ️ 的話會僅顯示 i :




如果要能顯示 emoji 字型須到 "工具/選項/主題 & 字型" 選單中將字型改為支援 emoji 的字型例如 "Segoe UI Emoji" :




這樣就會顯示 emoji 字元了 (但沒彩色) :




如果是在 Colab 或是 VS Code 編輯器上毋須設定字型直接複製貼上即可顯示 emoji 字元. 


2. 錯誤訊息框 st.error() : 

此元件用來顯示錯誤訊息, 常用的 emoji 為 ❌, 元件的背景色為紅色, 例如 : 


測試 2-1 : 用 st.error() 顯示錯誤訊息 [看原始碼]   

# st-error-test-1-1.py
import streamlit as st

st.subheader('錯誤 (error) 訊息框')
st.error('這是預設的錯誤訊息框')
st.error('這是有 emoji 的錯誤訊息框', icon="❌")

結果如下 : 




st.error() 通常用在 try except 架構中用來顯示捕捉到的例外與錯誤. 例如 :


測試 2-2 : 在 try except 中用 st.error() 顯示錯誤訊息 [看原始碼]   

# st-error-test-1-2.py
import streamlit as st

st.subheader('錯誤 (error) 訊息框')
try:
    result=1/0
except Exception as e:
    st.error(f'捕捉到除以 0 例外 ({e})', icon="❌")

結果如下 :




3. 警告訊息框 st.warning() : 

此元件用來顯示警告訊息, 常用的 emoji 為 ⚠️, 元件的背景色為黃色, 例如 : 


測試 3 : 用 st.warning() 顯示警告訊息 [看原始碼]   

# st-warning-test-1-1.py
import streamlit as st

st.subheader('警告 (warning) 訊息框')
st.warning('這是預設的警告訊息框')
st.warning('這是有 emoji 的警告訊息框', icon="⚠️")

結果如下 :




4. 成功訊息框 st.success() : 

此元件用來顯示成功訊息 (操作成功或任務完成), 常用的 emoji 為 ✅, 元件的背景色為綠色, 例如 : 


測試 4 : 用 st.success() 顯示成功訊息 [看原始碼]   

# st-success-test-1-1.py
import streamlit as st

st.subheader('成功 (success) 訊息框')
st.success('這是預設的成功訊息框')
st.success('這是有 emoji 的成功訊息框', icon="✅")

結果如下 :




5. 異常訊息元件 st.exception() : 

此元件用來顯示完整的錯誤追蹤訊息 (traceback), 傳入參數為一個 Python 例外物件, 主要是用來在開發與除錯中給程式設計師看的, 與 st.error() 用來顯示錯誤訊息給用戶看用途不同, 所以此函式沒有 icon 參數, 元件的背景色為紅色, 例如 : 


測試 5 : 用 st.exception() 顯示異常訊息 [看原始碼]   

# st-exception-test-1.py
import streamlit as st

st.subheader('異常 (exception) 訊息框')
try:
    result=1/0
except Exception as e:
    st.exception(e)

結果如下 :



2025年5月25日 星期日

2025 年第 21 周記事

本周高雄天氣熱爆, 每天下班回到家不到五點半, 去河堤快走還很熱, 只好先打打程式等到 6 點太陽西下才出發. 我的運動包現在除了帶肉肉條外還有一小瓶水與方形塑膠水盆, 讓河堤小咪吃完肉肉條再喝水 : 





五月以來咪咪與萬萬突然不吃我在家樂福超市買的乾糧了, 改吃肉泥, 肉肉條, 與貓罐罐. 經試用發現全聯賣的鮪魚+金線魚 (26 元) 他們超愛. 吃完的空罐頭洗乾淨後打算下周拿去河堤橋墩邊放幾個給貓咪喝水用, 有去運動時就補水, 城市的貓要找到乾淨的水很難. 




昨天 (週六) 老同學大帥與琪大師來訪, 暢談了一整天, 因中午要留他們在家吃個便飯, 所以我早上特地跑鎮上的市集一趟, 補些青菜豆腐與水果, 順便去幫水某找賣白木耳的攤子, 還真被我找到了, 原來店址就在原吳文禮診所啊! 見攤上有賣肉粽與鹼粽, 隨口問是否可預定下周端午節的粽子, 老闆說有, 一顆 35 元, 於是便各訂 1 串 (10 個). 我週五曾打電話向退伍軍人訂, 得知他們即將停業,  真可惜. 
 
本周專心測試 Streamlit 的輸入元件, 預計下周版面與容器測完應該就能完工了, 我原先預估需要兩個月, 沒想到推進得如此迅速. 另外是公司的 Hahow 企業版學習, 周一搜尋時意外找到 AI. Team 的 "全方位 LLM 實戰攻略:Code 出你的 AI 智能助理", 這門課長達 24 小時而且很硬, 本周已攻至第七章, 下周應該可以看完. 

周末這兩天傍晚仍然是給芭樂套袋, 兩天合計套了 160 顆, 去年買的 1000 個袋子下周應該會用完, 必須開車去資材行再買一包 :




今天早上去市集前順路到墓園巡視, 發現小徑已長滿雜草難行, 下周要帶打草機去打一打. 

2025年5月24日 星期六

Streamlit 學習筆記 : 使用者輸入元件 (十六) 拍照元件

本篇旨在測試 Streamlit 的拍照元件函式 st.download_button().

本系列所有測試文章參考 :


呼叫 st.download_button() 函式並傳入必要參數 label 會建立一個拍照元件, 按下按鈕可從電腦的照相機鏡頭拍照, 其參數結構如下 : 

st.camera_input(label, key=None, help=None, on_change=None, args=None, kwargs=None, disabled=False, label_visibility="visible")

st.camera_input() 的傳回值為 None 或 UploadedFile 物件 (ByteIO 的子類別). 
 
參數說明如下表 :


 st.camera_input() 參數  說明
label 元件的標籤文字
key 元件的唯一識別鍵,可用於 st.session_state
help 使用者滑鼠移到元件上時顯示的說明文字
on_change 當元件狀態改變時呼叫的回呼函式
args 傳給 on_change 回呼函式的額外引數 (以 tuple 傳遞)
kwargs 傳給 on_change 回呼函式的額外關鍵字引數 (以 dict 傳遞)
disabled 布林值,若為 True 則停用元件
label_visibility 設定標籤顯示方式:'visible'(預設)、'hidden' 或 'collapsed'


例如 : 


測試 1 : 下載文字檔 [看原始碼]   

# st-camera_input-test-1.py
import streamlit as st

picture=st.camera_input("請按 Take Photo 鈕拍照")
if picture:
    st.image(picture)
    st.write('已完成拍照')

此例執行時首先會彈出一個視窗詢問是否允許程式使用電腦的攝影鏡頭, 須按 "允許" 才會開啟攝像頭 : 




按下 Take Photo 鈕即拍照取得影像之 UploadedFile 物件, 然後傳給底下的 st.image() 顯示 : 




下面範例測試 on_change 與 args 參數的用法 :


測試 2 : 參數 on_change 與 args 用法 [看原始碼]   

# st-camera_input-test-2.py
import streamlit as st

def on_camera_change(name):
    picture=st.session_state['picture']
    if picture:
        st.image(picture, caption=f'**拍攝者 : {name}**')

picture=st.camera_input(
    '請按 Take Photo 鈕拍照',
    key='picture',
    on_change=on_camera_change,
    args=('Tony',)
    )

此例設定了 key 參數, 這樣 st.camera_input() 的傳回值 (UploadedFile 類別圖片) 就會以 picture 為鍵記錄在 st.session_state 字典裡, 當按下拍照件時會觸發 on_change 事件, 這時拍攝者名字會用 args 傳送給事件處理函式的 name 參數, 這時拍攝的照片會顯示在鏡頭上方 : 




但拍完照片鏡頭卻是空白 : 




這是正常現象, 原因是按下拍照鈕時會 st.camera_input() 會將拍攝的圖片存入 st.session_state[key] 內, 然後重新執行整支程式, 這時因為 st.session_state[key] 有保持圖片, 所以就不會開啟鏡頭, 必須按 Clear photo 鈕清除 st.session_state[key] 圖片後才會再次開啟鏡頭. 

上例也可以改用 kwargs 來傳引數給 on_change 事件處理函式, 例如 : 


測試 3 : 參數 on_change 與 kwargs 用法 [看原始碼]   

# st-camera_input-test-3.py
import streamlit as st

def on_camera_change(name):
    picture=st.session_state['picture']
    if picture:
        st.image(picture, caption=f'**拍攝者 : {name}**')

picture=st.camera_input(
    '請按 Take Photo 鈕拍照',
    key='picture',
    on_change=on_camera_change,
    kwargs={'name': 'Tony'}
    )

結果與上例一樣. 

Streamlit 學習筆記 : 使用者輸入元件 (十五) 檔案下載按鈕

本篇旨在測試 Streamlit 的檔案下載按鈕函式 st.download_button().

本系列所有測試文章參考 :


呼叫 st.download_button() 函式並傳入必要參數 label 與 data 會建立一個檔案下載按鈕, 按下按鈕可下載 data 參數之資料, 其參數結構如下 : 

st.download_button(label, data, file_name=None, mime=None, key=None, help=None, on_click=None, args=None, kwargs=None, disabled=False, use_container_width=False)

st.download_button() 傳回值為 True (有按下按鈕) 或 False (沒按按鈕). 
 
參數說明如下表 :


st.download_button() 參數 說明
label 按鈕上顯示的文字
data 要下載的資料,可以是 bytes、str、或檔案物件(如 BytesIO)
file_name 使用者下載時的檔名,若未提供,瀏覽器會使用預設名稱
mime MIME 類型(例如 "text/csv"、"application/pdf")
key 元件的唯一識別鍵,避免重複時出錯
help 滑鼠懸停時顯示的提示文字
on_click 按下按鈕時呼叫的函式
args 傳遞給 on_click 函式的非關鍵字參數 (tuple)
kwargs 傳遞給 on_click 函式的關鍵字參數 (dict)
disabled 若為 True,按鈕將被停用
use_container_width 若為 True,按鈕會撐滿容器寬度


其中的 mime 參數為與 data 資料內容對應之檔案類型, 若未指定則 Streamlit 會根據 file_name 參數的副檔名推斷後自動指定. 但為了避免誤判, 也為了下載時瀏覽器能正確識別檔案格式, 最好還是自行指定正確的 MIME 類型 (特別是二進位資料) 為宜.  

常用的 MIME 類型如下表 : 


 MIME 類型  說明
text/plain 一般純文字檔(如 .txt)
text/csv CSV 檔案(如 .csv)
text/html HTML 檔案
application/json JSON 檔案
application/pdf PDF 文件
application/xml XML 資料
application/vnd.ms-excel Excel 檔(.xls,舊版格式)
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet Excel 檔(.xlsx,新版格式)
application/zip ZIP 壓縮檔
image/png PNG 圖片
image/jpeg JPEG 圖片
image/svg+xml SVG 向量圖
image/gif GIF 動圖
audio/mpeg MP3 音訊
audio/wav WAV 音訊
video/mp4 MP4 影片


例如 : 


測試 1 : 下載文字檔 [看原始碼]   

# st-download_button-test-1.py
import streamlit as st

text='Hello World!'
download=st.download_button(
    label='下載文字檔',
    data=text,
    file_name='hello.txt',
    mime='text/plain'
    )
if download:
    st.write('檔案已下載')

結果如下 : 




也可以用 open() 開啟任何檔案, 然後設定正確之 MIME 類型, 下面是下載本機 PDF 檔的範例 :


測試 2 : 下載 PDF 檔 [看原始碼]   

# st-download_button-test-2.py
import streamlit as st

with open('sample.pdf', 'rb') as f:
    pdf_bytes=f.read()  # 讀取本地 PDF 檔案
    
st.download_button(
    label='下載 PDF 文件',
    data=pdf_bytes,
    file_name='downloaded_sample.pdf',
    mime='application/pdf'
    )

此例先用 open() 開啟本機目錄下的 PDF 檔為 Bytes 類型資料, 將 mime 參數設為 application/pdf 即可正確下載, 結果如下 : 




下面範例測試 on_click 與 args 參數的用法 :


測試 3 : 參數 on_click 與 args 用法 [看原始碼]   

# st-download_button-test-3.py
import streamlit as st

def on_click_download(original, downloaded):
    st.write(f'檔案 {original} 已被下載為 {downloaded}')

with open('sample.pdf', 'rb') as f:
    pdf_bytes=f.read()  # 讀取本地 PDF 檔案
    
st.download_button(
    label='下載 PDF 文件',
    data=pdf_bytes,
    file_name='downloaded_sample.pdf',
    mime='application/pdf',
    on_click=on_click_download,
    args=('sample.pdf', 'downloaded_sample.pdf')    
    )

由於 st.download_button() 傳回 True/False, 故此例沒有設定 key 來取得傳回值. 按下按鈕時會將 args 的兩個引數傳遞給 on_click 事件處理函式的 original 與 downloaded 參數, 結果如下 : 




此例也可以用 kwargs 參數來做, 例如 : 


測試 4 : 參數 on_click 與 kwargs 用法 [看原始碼]   

# st-download_button-test-4.py
import streamlit as st

def on_click_download(original, downloaded):
    st.write(f'檔案 {original} 已被下載為 {downloaded}')

with open('sample.pdf', 'rb') as f:
    pdf_bytes=f.read()  # 讀取本地 PDF 檔案
    
st.download_button(
    label='下載 PDF 文件',
    data=pdf_bytes,
    file_name='downloaded_sample.pdf',
    mime='application/pdf',
    on_click=on_click_download,
    kwargs={'original': 'sample.pdf', 'downloaded': 'downloaded_sample.pdf'}    
    )

此例改用 kwargs 字典來傳遞兩個引數, 結果與上例相同. 

2025年5月23日 星期五

Streamlit 學習筆記 : 使用者輸入元件 (十四) 檔案上傳器

本篇旨在測試 Streamlit 的檔案上傳器函式 st.file_uploader().

本系列所有測試文章參考 :


呼叫 st.file_uploader 函式並傳入必要參數 label 會建立一個檔案上傳按鈕, 按下按鈕會開啟檔按選取視窗選擇要上傳的檔案, 其參數結構如下 : 

st.file_uploader(label, type=None, accept_multiple_files=False, key=None, help=None, on_change=None, args=None, kwargs=None, disabled=False, label_visibility="visible")

st.file_uploader 傳回值是 UploadedFile 物件 (單檔) 或 UploadedFile 物件串列 (多檔), 若未上船任何檔案則傳回 None (單檔) 或空串列(多檔). UploadedFile 物件是 ByteIO 的子類別, 可以傳給任何處理圖檔的函式做進一步處理. 
 
參數說明如下表 :


st.file_uploader() 之參數 說明
label 元件的標籤文字。
type 允許上傳的檔案副檔名列表,例如 ["jpg", "png"],預設為 None(接受所有類型)。
accept_multiple_files 是否允許多檔上傳,布林值,預設為 False。
key 為此元件指定唯一識別字串,以便使用 st.session_state 存取。
help 顯示於元件旁邊的說明提示,滑鼠懸停時可見。
on_change 使用者與元件互動後要執行的函式。
args 傳入 on_change 回呼函式的位置參數 (tuple)。
kwargs 傳入 on_change 回呼函式的關鍵字參數 (dict)。
disabled 是否停用元件,預設為 False。
label_visibility 標籤是否顯示,可設為 "visible"、"hidden" 或 "collapsed"。


檔案上傳按鈕預設是上傳單一檔案, 但可以傳入 accept_multiple_files=True 設定為可上傳多個檔案, 例如 : 


測試 1 : 上傳單一檔案 [看原始碼]       

# st-file_uploader-test-1.py
import streamlit as st
from PIL import Image

st.subheader('上傳單一檔案 (圖片)')
file=st.file_uploader('請上傳圖片', type=['jpg', 'png', 'jpeg'])
if file:
    image=Image.open(uploaded_file)
    st.image(image, caption=file.name)

此例使用 Pillow (PIL) 套件的 Image.read() 函式來開啟上傳之 UploadedFile 物件, 然後用 st.image() 來顯示此圖片. 按 "Browse files" 鈕選擇要上傳的檔案 :




type 參數會限制僅顯示副檔名為 .jpg, .png, .jpeg 的檔案 :





可見上傳完成後會在按鈕下方顯示所上傳之檔案檔名與大小. 如果再次按 "Browse files" 鈕選擇要另一個圖檔上傳, 它將取代之前上傳的檔案 :




下面範例將 accept_multiple_files 設為 True 以便能上傳多個檔案 :


測試 2 : 上傳多個檔案 [看原始碼]       

# st-file_uploader-test-2.py
import streamlit as st
from PIL import Image

st.subheader('上傳多個檔案 (圖片)')
files=st.file_uploader(
    '請上傳圖片',
    type=['jpg', 'png', 'jpeg'],
    accept_multiple_files=True
    )
if files:
    for file in files:
        image=Image.open(file)
        st.image(file, caption=file.name)

此例 file_uploader() 傳回一個串列, 所以用一個迴圈走訪每一個 UploadedFile 物件並用 st.image() 來顯示圖片 :




可以按住 Ctrl 或 Shift 鍵選擇多個檔案同時上傳 :




可見按鈕下方會顯示已上傳檔案清單 :




下面是 on_change 與 args 參數測試範例 :


測試 3 : 參數 on_change 與 args 用法 [看原始碼] 

# st-file_uploader-test-3.py
import streamlit as st

def on_upload_change(label):
    st.success(f'{label}檔案已上傳!')
    file=st.session_state['file']
    if file:
        st.write(f'檔名:{file.name}')
        st.write(f'大小:{file.size} bytes')

st.file_uploader(
    '請上傳檔案',
    type=['txt', 'pdf', 'docx'],
    key='file',
    on_change=on_upload_change,
    args=('機密',)
    )

此例利用 args 傳送引數給 on_change 事件處理函式的 label 參數, st.file_uploader() 的傳回值 (UploadedFile 物件) 會以 'file' 為鍵儲存在 st.session_state 字典裡, 結果如下 :






也可以用 kwargs 參數來傳遞引數, 例如 : 


測試 4 : 參數 on_change 與 kwargs 用法 [看原始碼] 

# st-file_uploader-test-4.py
import streamlit as st

def on_upload_change(label):
    st.success(f'{label}檔案已上傳!')
    file=st.session_state['file']
    if file:
        st.write(f'檔名:{file.name}')
        st.write(f'大小:{file.size} bytes')

st.file_uploader(
    '請上傳檔案',
    type=['txt', 'pdf', 'docx'],
    key='file',
    on_change=on_upload_change,
    kwargs={'label': '機密'}
    )

結果與上面範例相同.

Streamlit 學習筆記 : 使用者輸入元件 (十三) 顏色選擇器

本篇旨在測試 Streamlit 的顏色選擇器函式 st.color_picker().

本系列所有測試文章參考 :


呼叫 st.color_picker() 函式並傳入必要參數 label 會建立一個時間選擇器, 其參數結構如下 : 

st.color_picker(label, value='#000000', key=None, help=None, on_change=None, args=None, kwargs=None, disabled=False, label_visibility="visible")

st.color_picker 傳回值是格式為 "#RRGGBB" 的 16 進位色碼, 其中 RR(紅)/GG(綠)/BB (藍) 為 0~F 的字元, 例如 '#FF0000' 為紅色. 

參數說明如下表 :


 st.color_picker() 參數  說明
label 元件標籤文字,會顯示在選色器旁。
value 預設顏色,需為 HEX 字串格式(如 "#ff0000"),預設為 "#000000"。
key 元件的唯一識別字串,用於 st.session_state。
help 滑鼠移至元件上方時顯示的提示訊息。
on_change 使用者改變選色時觸發的回呼函式。
args 傳遞給 on_change 回呼函式的位置參數(tuple)。
kwargs 傳遞給 on_change 回呼函式的關鍵字參數(dict)。
disabled 設為 True 時會讓選色器無法互動。
label_visibility 控制標籤可見性,可選 "visible"(預設)、"hidden" 或 "collapsed"。


例如 : 


測試 1 : 預設的顏色選擇器 [看原始碼]    

# st-color_picker-test-1.py
import streamlit as st

selected=st.color_picker('請選擇顏色 :')
if selected:
    st.write(selected)

預設選取黑色 (#000000), 按色塊會彈出調色盤與色碼輸入框, 可以直接在調色盤上點選顏色, 或在下方輸入框填入 16 進位色碼, 按輸入框右邊的按鈕可以切換 HEX/RGB/HSL 色彩模式 :




選取顏色後再按一次色塊即可更改顏色並關閉調色盤 : 




可以用 value 設定預設選取顏色, 例如 : 


測試 2 : 參數 value 用法 [看原始碼] 

# st-color_picker-test-2.py
import streamlit as st

selected=st.color_picker('請選擇顏色 :', value='#1177bb')
if selected:
    st.write(selected)

結果如下 :




下面是 on_change 與 args 參數測試範例 :


測試 3 : 參數 on_change 與 args 用法 [看原始碼] 

# st-color_picker-test-3.py
import streamlit as st

def on_color_change(part):
    color_code=st.session_state['color_code']
    st.write(f'{part} 顏色已被修改為 : {color_code}')

part=st.text_input('請輸入修改部分:', '背景')
st.color_picker(
    '請選擇顏色 :',
    key='color_code',
    on_change=on_color_change,
    args=(part,)
    )

此例




選好顏色再按一次色塊確定變更顏色 : 




上例也可以用 kwargs 參數來達成 : 


測試 4 : 參數 on_change 與 kwargs 用法 [看原始碼

# st-color_picker-test-4.py
import streamlit as st

def on_color_change(part):
    color_code=st.session_state['color_code']
    st.write(f'{part} 顏色已被修改為 : {color_code}')

part=st.text_input('請輸入修改部分:', '背景')
st.color_picker(
    '請選擇顏色 :',
    key='color_code',
    on_change=on_color_change,
    kwargs={'part': part}
    )

結果與上面相同.

Streamlit 學習筆記 : 使用者輸入元件 (十二) 時間選擇器

本篇旨在測試 Streamlit 的時間輸入函式 st.time_input().

本系列所有測試文章參考 :


呼叫 st.time_input() 函式並傳入必要參數 label 會建立一個時間選擇器, 其參數結構如下 : 

st.time_input(label, value=None, key=None, help=None, on_change=None, args=None, kwargs=None, disabled=False, label_visibility="visible", step=timedelta(minutes=1))

st.time_input() 的傳回值為 datetime.time 物件, 用 st.write() 等函式輸出時預設會用 HH:MM:SS 字串格式顯示. 

參數說明如下表 :


st.time_input() 之參數 說明
label 時間輸入欄的標籤。
value 預設時間,可為 datetime.time 或 datetime.datetime。預設為當前時間。
key 用來識別元件的唯一鍵值。若不指定,則根據程式碼位置自動產生。
help 滑鼠移到元件上方時顯示的提示文字。
on_change 當輸入的時間變更時要呼叫的函式。
args 傳遞給 on_change 函式的位置參數 (tuple)。
kwargs 傳遞給 on_change 函式的關鍵字參數 (dict)。
disabled 布林值,若為 True,元件會被禁用。
label_visibility 標籤是否顯示,可為 "visible"(預設)、"hidden" 或 "collapsed"。
step 可選時間的間隔,以 datetime.timedelta 表示。預設為 1 分鐘。


例如 : 


測試 1 : 預設的時間選擇器 [看原始碼] 

# st-time_input-test-1.py
import streamlit as st

selected=st.time_input('請選擇時間 :')
if selected:
    st.write(selected)

預設會顯示目前時間 :




點選下拉式選單可選取時間, 預設間隔為 15 分鐘 : 





可以傳入 value 與 step 參數設定預設時間與間隔, 這需要用到 datetime.time() 與 datetime.timedelta() 函式, 如下例所示 : 


測試 2 : 參數 value 與 step 用法 [看原始碼] 

# st-time_input-test-2.py
import streamlit as st
from datetime import time, timedelta

default_time=time(8, 30)    # 傳入時與分
step=timedelta(minutes=10)   # 傳入分鐘間隔
selected=st.time_input('請選擇時間 :', value=default_time, step=step)
if selected:
    st.write(selected)

此例呼叫 datetime.time() 傳入時與分建立 time 物件; 呼叫 datetime.timedelta() 傳入分鐘間隔建立 timedelta 物件, 分別傳給 value 與 step 參數, 結果如下 : 







下面是 on_change 與 args 參數測試範例 :


測試 3 : 參數 on_change 與 args 用法 [看原始碼] 

# st-time_input-test-3.py
import streamlit as st

def show_meeting_time(agenda):
    meeting_time=st.session_state['meeting_time']
    st.write(f'{agenda} 會議時間 {meeting_time}')

agenda=st.text_input('請輸入議程:', '年度計畫討論會')
st.time_input(
    '請選擇時間 :',
    key='meeting_time',
    on_change=show_meeting_time,
    args=(agenda,)
    )

此例使用 args 傳送 agenda 引數給 on_change 事件處理函式的 agenda 參數, 另外設定 key 參數以便時間選擇器的值 (datetime.time 物件) 能以此為鍵儲存於 st.seesion_state 字典中, 結果如下 :





上例的引數也可以用 kwargs, 例如 : 


測試 4 : 參數 on_change 與 kwargs 用法 [看原始碼] 

# st-time_input-test-4.py
import streamlit as st

def show_meeting_time(agenda):
    meeting_time=st.session_state['meeting_time']
    st.write(f'{agenda} 會議時間 {meeting_time}')

agenda=st.text_input('請輸入議程:', '年度計畫討論會')
st.time_input(
    '請選擇時間 :',
    key='meeting_time',
    on_change=show_meeting_time,
    kwargs={'agenda': agenda}
    )

結果與上例相同.