我的 Pi 400 上的共用 Python 虛擬環境 myenv313 已配置完成, 基本上用來測試與佈署機器學習與量化投資 App. 但 Streamlit 不能在此環境中安裝, 因為它依賴的底層 C/C++ 擴充程式會破壞其他套件 (例如 Pandas), 必須在獨立的虛擬環境中安裝.
1. 建立一個虛擬環境 streamlit_venv 安裝 Streamlit :
pi@raspberrypi:~ $ python -m venv streamlit_venv
pi@raspberrypi:~ $ source ~/streamlit_venv/bin/activate
(streamlit_venv) pi@raspberrypi:~ $ pip install streamlit --no-cache-dir
Collecting streamlit
Downloading streamlit-1.52.1-py3-none-any.whl.metadata (9.8 kB)
Collecting altair!=5.4.0,!=5.4.1,<7,>=4.0 (from streamlit)
Downloading altair-6.0.0-py3-none-any.whl.metadata (11 kB)
Collecting blinker<2,>=1.5.0 (from streamlit)
Downloading blinker-1.9.0-py3-none-any.whl.metadata (1.6 kB)
Collecting cachetools<7,>=4.0 (from streamlit)
Downloading cachetools-6.2.2-py3-none-any.whl.metadata (5.6 kB)
Collecting click<9,>=7.0 (from streamlit)
Downloading click-8.3.1-py3-none-any.whl.metadata (2.6 kB)
Collecting numpy<3,>=1.23 (from streamlit)
Downloading numpy-2.3.5-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.metadata (62 kB)
Collecting packaging>=20 (from streamlit)
Downloading packaging-25.0-py3-none-any.whl.metadata (3.3 kB)
Collecting pandas<3,>=1.4.0 (from streamlit)
Downloading pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl.metadata (91 kB)
Collecting pillow<13,>=7.1.0 (from streamlit)
Downloading pillow-12.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.metadata (8.8 kB)
Collecting protobuf<7,>=3.20 (from streamlit)
Downloading protobuf-6.33.2-cp39-abi3-manylinux2014_aarch64.whl.metadata (593 bytes)
Collecting pyarrow>=7.0 (from streamlit)
Downloading pyarrow-22.0.0-cp313-cp313-manylinux_2_28_aarch64.whl.metadata (3.2 kB)
Collecting requests<3,>=2.27 (from streamlit)
Downloading requests-2.32.5-py3-none-any.whl.metadata (4.9 kB)
Collecting tenacity<10,>=8.1.0 (from streamlit)
Downloading tenacity-9.1.2-py3-none-any.whl.metadata (1.2 kB)
Collecting toml<2,>=0.10.1 (from streamlit)
Downloading toml-0.10.2-py2.py3-none-any.whl.metadata (7.1 kB)
Collecting typing-extensions<5,>=4.4.0 (from streamlit)
Downloading typing_extensions-4.15.0-py3-none-any.whl.metadata (3.3 kB)
Collecting watchdog<7,>=2.1.5 (from streamlit)
Downloading watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl.metadata (44 kB)
Collecting gitpython!=3.1.19,<4,>=3.0.7 (from streamlit)
Downloading gitpython-3.1.45-py3-none-any.whl.metadata (13 kB)
Collecting pydeck<1,>=0.8.0b4 (from streamlit)
Downloading pydeck-0.9.1-py2.py3-none-any.whl.metadata (4.1 kB)
Collecting tornado!=6.5.0,<7,>=6.0.3 (from streamlit)
Downloading tornado-6.5.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.metadata (2.8 kB)
Collecting jinja2 (from altair!=5.4.0,!=5.4.1,<7,>=4.0->streamlit)
Downloading jinja2-3.1.6-py3-none-any.whl.metadata (2.9 kB)
Collecting jsonschema>=3.0 (from altair!=5.4.0,!=5.4.1,<7,>=4.0->streamlit)
Downloading jsonschema-4.25.1-py3-none-any.whl.metadata (7.6 kB)
Collecting narwhals>=1.27.1 (from altair!=5.4.0,!=5.4.1,<7,>=4.0->streamlit)
Downloading narwhals-2.13.0-py3-none-any.whl.metadata (12 kB)
Collecting gitdb<5,>=4.0.1 (from gitpython!=3.1.19,<4,>=3.0.7->streamlit)
Downloading gitdb-4.0.12-py3-none-any.whl.metadata (1.2 kB)
Collecting smmap<6,>=3.0.1 (from gitdb<5,>=4.0.1->gitpython!=3.1.19,<4,>=3.0.7->streamlit)
Downloading smmap-5.0.2-py3-none-any.whl.metadata (4.3 kB)
Collecting python-dateutil>=2.8.2 (from pandas<3,>=1.4.0->streamlit)
Downloading python_dateutil-2.9.0.post0-py2.py3-none-any.whl.metadata (8.4 kB)
Collecting pytz>=2020.1 (from pandas<3,>=1.4.0->streamlit)
Downloading pytz-2025.2-py2.py3-none-any.whl.metadata (22 kB)
Collecting tzdata>=2022.7 (from pandas<3,>=1.4.0->streamlit)
Downloading tzdata-2025.2-py2.py3-none-any.whl.metadata (1.4 kB)
Collecting charset_normalizer<4,>=2 (from requests<3,>=2.27->streamlit)
Downloading charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.metadata (37 kB)
Collecting idna<4,>=2.5 (from requests<3,>=2.27->streamlit)
Downloading idna-3.11-py3-none-any.whl.metadata (8.4 kB)
Collecting urllib3<3,>=1.21.1 (from requests<3,>=2.27->streamlit)
Downloading urllib3-2.6.1-py3-none-any.whl.metadata (6.6 kB)
Collecting certifi>=2017.4.17 (from requests<3,>=2.27->streamlit)
Downloading certifi-2025.11.12-py3-none-any.whl.metadata (2.5 kB)
Collecting MarkupSafe>=2.0 (from jinja2->altair!=5.4.0,!=5.4.1,<7,>=4.0->streamlit)
Downloading markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.metadata (2.7 kB)
Collecting attrs>=22.2.0 (from jsonschema>=3.0->altair!=5.4.0,!=5.4.1,<7,>=4.0->streamlit)
Downloading attrs-25.4.0-py3-none-any.whl.metadata (10 kB)
Collecting jsonschema-specifications>=2023.03.6 (from jsonschema>=3.0->altair!=5.4.0,!=5.4.1,<7,>=4.0->streamlit)
Downloading jsonschema_specifications-2025.9.1-py3-none-any.whl.metadata (2.9 kB)
Collecting referencing>=0.28.4 (from jsonschema>=3.0->altair!=5.4.0,!=5.4.1,<7,>=4.0->streamlit)
Downloading referencing-0.37.0-py3-none-any.whl.metadata (2.8 kB)
Collecting rpds-py>=0.7.1 (from jsonschema>=3.0->altair!=5.4.0,!=5.4.1,<7,>=4.0->streamlit)
Downloading rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.metadata (4.1 kB)
Collecting six>=1.5 (from python-dateutil>=2.8.2->pandas<3,>=1.4.0->streamlit)
Downloading six-1.17.0-py2.py3-none-any.whl.metadata (1.7 kB)
Downloading streamlit-1.52.1-py3-none-any.whl (9.0 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 9.0/9.0 MB 4.8 MB/s eta 0:00:00
Downloading altair-6.0.0-py3-none-any.whl (795 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 795.4/795.4 kB 5.4 MB/s eta 0:00:00
Downloading blinker-1.9.0-py3-none-any.whl (8.5 kB)
Downloading cachetools-6.2.2-py3-none-any.whl (11 kB)
Downloading click-8.3.1-py3-none-any.whl (108 kB)
Downloading gitpython-3.1.45-py3-none-any.whl (208 kB)
Downloading gitdb-4.0.12-py3-none-any.whl (62 kB)
Downloading numpy-2.3.5-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (14.2 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 14.2/14.2 MB 4.4 MB/s eta 0:00:00
Downloading pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl (11.7 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 11.7/11.7 MB 4.9 MB/s eta 0:00:00
Downloading pillow-12.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (6.3 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 6.3/6.3 MB 4.0 MB/s eta 0:00:00
Downloading protobuf-6.33.2-cp39-abi3-manylinux2014_aarch64.whl (324 kB)
Downloading pydeck-0.9.1-py2.py3-none-any.whl (6.9 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 6.9/6.9 MB 4.4 MB/s eta 0:00:00
Downloading requests-2.32.5-py3-none-any.whl (64 kB)
Downloading charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (147 kB)
Downloading idna-3.11-py3-none-any.whl (71 kB)
Downloading smmap-5.0.2-py3-none-any.whl (24 kB)
Downloading tenacity-9.1.2-py3-none-any.whl (28 kB)
Downloading toml-0.10.2-py2.py3-none-any.whl (16 kB)
Downloading tornado-6.5.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (445 kB)
Downloading typing_extensions-4.15.0-py3-none-any.whl (44 kB)
Downloading urllib3-2.6.1-py3-none-any.whl (131 kB)
Downloading watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl (79 kB)
Downloading certifi-2025.11.12-py3-none-any.whl (159 kB)
Downloading jinja2-3.1.6-py3-none-any.whl (134 kB)
Downloading jsonschema-4.25.1-py3-none-any.whl (90 kB)
Downloading attrs-25.4.0-py3-none-any.whl (67 kB)
Downloading jsonschema_specifications-2025.9.1-py3-none-any.whl (18 kB)
Downloading markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (24 kB)
Downloading narwhals-2.13.0-py3-none-any.whl (426 kB)
Downloading packaging-25.0-py3-none-any.whl (66 kB)
Downloading pyarrow-22.0.0-cp313-cp313-manylinux_2_28_aarch64.whl (45.0 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 45.0/45.0 MB 4.6 MB/s eta 0:00:00
Downloading python_dateutil-2.9.0.post0-py2.py3-none-any.whl (229 kB)
Downloading pytz-2025.2-py2.py3-none-any.whl (509 kB)
Downloading referencing-0.37.0-py3-none-any.whl (26 kB)
Downloading rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (389 kB)
Downloading six-1.17.0-py2.py3-none-any.whl (11 kB)
Downloading tzdata-2025.2-py2.py3-none-any.whl (347 kB)
Installing collected packages: pytz, watchdog, urllib3, tzdata, typing-extensions, tornado, toml, tenacity, smmap, six, rpds-py, pyarrow, protobuf, pillow, packaging, numpy, narwhals, MarkupSafe, idna, click, charset_normalizer, certifi, cachetools, blinker, attrs, requests, referencing, python-dateutil, jinja2, gitdb, pydeck, pandas, jsonschema-specifications, gitpython, jsonschema, altair, streamlit
Successfully installed MarkupSafe-3.0.3 altair-6.0.0 attrs-25.4.0 blinker-1.9.0 cachetools-6.2.2 certifi-2025.11.12 charset_normalizer-3.4.4 click-8.3.1 gitdb-4.0.12 gitpython-3.1.45 idna-3.11 jinja2-3.1.6 jsonschema-4.25.1 jsonschema-specifications-2025.9.1 narwhals-2.13.0 numpy-2.3.5 packaging-25.0 pandas-2.3.3 pillow-12.0.0 protobuf-6.33.2 pyarrow-22.0.0 pydeck-0.9.1 python-dateutil-2.9.0.post0 pytz-2025.2 referencing-0.37.0 requests-2.32.5 rpds-py-0.30.0 six-1.17.0 smmap-5.0.2 streamlit-1.52.1 tenacity-9.1.2 toml-0.10.2 tornado-6.5.3 typing-extensions-4.15.0 tzdata-2025.2 urllib3-2.6.1 watchdog-6.0.0
Pi 400 有 4GB 記憶體, 跑起來就是快. 檢視 Streamlit 版本 :
(streamlit_venv) pi@raspberrypi:~ $ python
Python 3.13.5 (main, Jun 25 2025, 18:55:22) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import streamlit as st
>>> st.__version__
'1.52.1'
檢視虛擬目錄下的套件 :
(streamlit_venv) pi@raspberrypi:~ $ pip list
Package Version
------------------------- -----------
altair 6.0.0
attrs 25.4.0
blinker 1.9.0
cachetools 6.2.2
certifi 2025.11.12
charset-normalizer 3.4.4
click 8.3.1
gitdb 4.0.12
GitPython 3.1.45
idna 3.11
Jinja2 3.1.6
jsonschema 4.25.1
jsonschema-specifications 2025.9.1
MarkupSafe 3.0.3
narwhals 2.13.0
numpy 2.3.5
packaging 25.0
pandas 2.3.3
pillow 12.0.0
pip 25.1.1
protobuf 6.33.2
pyarrow 22.0.0
pydeck 0.9.1
python-dateutil 2.9.0.post0
pytz 2025.2
referencing 0.37.0
requests 2.32.5
rpds-py 0.30.0
six 1.17.0
smmap 5.0.2
streamlit 1.52.1
tenacity 9.1.2
toml 0.10.2
tornado 6.5.3
typing_extensions 4.15.0
tzdata 2025.2
urllib3 2.6.1
watchdog 6.0.0
依賴的大套件包括 Numpy, Pandas, 與 Pyarrow.
2. 本機測試 Streamlit app :
我從王進德老師的 "Raspberry Pi 5 + AI創新實踐 : 電腦視覺與人工智慧應用指南" 書中找到一個範例來測試:
將此程式取名 interactive_ui.py 存在 streamlit_app 資料夾下 :
# interactive_ui.py
import streamlit as st
import datetime
from time import sleep
st.title("互動元件")
# 加入單行文字輸入框
st.subheader("text input")
name=st.text_input("Enter you name:")
st.write(f"Hello, {name}")
# 加入多行文字輸入框
message=st.text_area("Enter your message:")
st.write("Your message:")
st.write(message)
# 加入數值輸入框
st.subheader("number input")
age=st.number_input("Enter your age:", min_value=0, max_value=120)
st.write(f"Your age is {age}")
# 加入按鈕
st.subheader("Button")
if st.button('Click Me'):
st.write("Button clicked!")
# 加入單選鈕
st.subheader("Radio and checkbox")
gender = st.radio("Select your gender:", ["Male", "Female", "Other"],
horizontal=True)
st.write(f"You selected {gender}")
# 加入複選框
agree= st.checkbox("I agree to the terms and conditions")
if agree:
st.write("Thank you for agreeing!")
# 加入下拉式選單
st.subheader("select box")
fruit = st.selectbox("Your favorite fruit:", ["Apple", "Banana", "Cherry"])
st.write(f"You selected {fruit}")
# 加入可複選的下拉式選單
options = st.multiselect("Your favorite colors:", ["Red", "Green", "Blue"])
st.write(f"You selected {options}")
# 加入滑桿
st.subheader("slider")
value = st.slider("Select a value:", 0, 100, 50)
st.write(f"Selected value: {value}")
# 加入值範圍滑桿
range_value = st.slider("Select a range of value:", 0, 100, (20, 80))
st.write(f"Selected range: {range_value}")
# 加入日期選擇器
st.subheader("date and time")
date = st.date_input("Select a date:", datetime.datetime.now())
st.write(f"Selected data: {date}")
# 加入時間選擇器
time = st.time_input("Select a time:", datetime.time(12,30))
st.write(f"Selected time: {time}")
# 加入進度條
st.subheader("progress and spinner")
progress_bar=st.progress(0)
for value in range(101):
progress_bar.progress(value)
sleep(0.1)
st.write("Done")
# 加入旋轉指示器
with st.spinner("等待中..."):
sleep(10)
st.success('Done')
Streamlit 程式不可在 Thonny 中直接執行, 必須在終端機用 streamlit run 執行 :
(streamlit_venv) pi@raspberrypi:~/streamlit_app $ streamlit run interactive_ui.py
You can now view your Streamlit app in your browser.
Local URL: http://localhost:8501
Network URL: http://192.168.50.74:8501
它會自動開啟 Chromium 瀏覽器展示結果網頁, 但同時也出現了一個顯示 "開啟你的設定檔時發生錯誤, 部分功能無法使用" 的視窗 :
問 AI 得知原因很多, 對 Pi 400 最可能的原因是 Chromium 設定檔損毀, 通常是非正常關機或 Chromium 跑一半被 kill 掉造成, 解決辦法很簡單, 就是刪除目前的 Chromium 設定檔, 然後重開瀏覽器即可 :
mv ~/.config/chromium ~/.config/chromium_backup
重新執行上面的 interactive_ui.py 就會開啟 Chromium, 果然就解決了.
關於 Streamlit 用法參考 :
3. 用 ngrok 讓外部可存取 Streamlit app :
用 wget 指令下載 64 位元版的 ngrok :
pi@raspberrypi:~ $ wget https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-linux-arm64.tgz
--2025-12-11 16:15:07-- https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-linux-arm64.tgz
正在查找主機 bin.equinox.io (bin.equinox.io)... 35.71.179.82, 13.248.244.96, 99.83.220.108, ...
正在連接 bin.equinox.io (bin.equinox.io)|35.71.179.82|:443... 連上了。
已送出 HTTP 要求,正在等候回應... 200 OK
長度: 10292787 (9.8M) [application/octet-stream]
儲存到:「ngrok-v3-stable-linux-arm64.tgz」
ngrok-v3-stable-lin 100%[===================>] 9.82M 736KB/s 於 19s
2025-12-11 16:15:27 (518 KB/s) - 已儲存 「ngrok-v3-stable-linux-arm64.tgz」 [10292787/10292787]
用 tar 解壓縮, 這會得到一個單一的執行檔 ngrok :
pi@raspberrypi:~ $ tar -xvf ngrok-v3-stable-linux-arm64.tgz
ngrok
用 mv 指令將 ngrok 執行檔移動到 PATH 目錄 :
pi@raspberrypi:~ $ sudo mv ngrok /usr/local/bin/
檢視 ngrok 版本 :
pi@raspberrypi:~ $ ngrok --version
ngrok version 3.34.0
然後註冊 & 登入 ngrok 官網取得 authtoken (認證金鑰), 由於 ngrok 免費帳戶只能用在一個連線, 所以此處我改用 Gmail 註冊了第二個帳戶 (注意, 不是直接用 Gmail 帳戶) :
按 Copy 複製金鑰 :
加入 ngrok authtoken (認證金鑰) :
pi@raspberrypi:~ $ ngrok config add-authtoken 1n4Ebyjktony1966PyZVSQ1nKz8Mn_tony1966At62W7RGhsx1L
Authtoken saved to configuration file: /home/pi/.config/ngrok/ngrok.yml
金鑰會存入 .config/ngrok/ngrok.yml 檔案中.
然後執行下列指令即可得到一個對外得 https 網址 :
ngrok http 本機埠號
pi@raspberrypi:~ $ ngrok http 8501
可見 ngrok 會將上面的本機區網網址 http://192.168.50.74:8501 映射到公網網址 https://02433506593c.ngrok-free.app/ :
這樣就可以從公網存取這個本機網站了.




沒有留言:
張貼留言