2025年12月25日 星期四

小米裕誠店購買除塵蟎機 (補記)

因為我有鼻子過敏, 對塵蹣非常敏感 (有一次全家去清境農場民宿住宿, 晚上被子拿出來一鋪馬上狂打噴嚏), 上週三下班後去河堤取書順著裕誠路到小米店買了一台小米除蹣機 Pro 版, 此款有一個顯示面板顯示除蟎強度與塵蹣濃度, 附紫外線殺菌與 50 度熱風乾燥功能 : 





回家先給床墊與睡袋除蟎, 哇, 吸出好多粉塵. 周五晚上帶回鄉下吸, 更恐怖. 

2025年12月24日 星期三

K 線圖套件 kbar 升版 v0.1.5

這兩天在樹莓派 Pi 3B 與 3A+ 這兩塊主機的 Bulleye OS 上安裝套件時都在安裝 kbar 的依賴套件 pyarrow 時失敗, 再次詢問 ChatGPT 才知道根本不需要將 pyarrow 列入依賴套件, 因為 kbar 原始碼既沒有 import pyarrow, 用來處理資料的 pandas 與畫 K 線的 mplfinance 也沒用到, 為何當時 ChatGPT 幫我寫  project.toml 時會列入 pyarrow? 為了拿掉 pyarrow 依賴只好升版為 v0.1.5 (同時也把版本上限加回去避免依賴套件大升版時出問題). 本系列之前文張參考 :



1. 修改 project.toml :  

黃底色部分為修改之處 : 

[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "kbar"
version = "0.1.5"
description = "A lightweight K-line (candlestick) plotting tool with matplotlib and mplfinance."
readme = "README.md"
requires-python = ">=3.9"
license = { file = "LICENSE" }
authors = [
  { name = "Tony Y.H. Huang" }
]
keywords = ["finance", "candlestick", "mplfinance", "k-line", "stock"]
classifiers = [
  "Development Status :: 3 - Alpha",
  "Intended Audience :: Developers",
  "Intended Audience :: Financial and Insurance Industry",
  "Programming Language :: Python :: 3",
  "License :: OSI Approved :: MIT License",
  "Operating System :: OS Independent"
]


dependencies = [
  "numpy>=1.23,<3.0",
  "pandas>=2.0,<3.0",
  "matplotlib>=3.7,<4.0",
  "mplfinance>=0.12.10b0,<1.0",
]

[project.optional-dependencies]
dev = [
  "pytest>=8.0",
  "coverage>=7.0"
]

[tool.pytest.ini_options]
addopts = "-v --maxfail=3 --disable-warnings"
testpaths = ["tests"]

[tool.coverage.run]
branch = true
source = ["kbar"]

[tool.coverage.report]
show_missing = true
skip_covered = true

[tool.setuptools.packages.find]
where = ["src"]  

[project.urls]
"Homepage" = "https://github.com/tony1966/kbar/"
"Bug Tracker" = "https://github.com/tony1966/kbar/issues"
"Documentation" = "https://github.com/tony1966/kbar/#readme"


2. 修改 src/kbar/__init__.py :

修改版本號碼 :

"""
KBar: A lightweight stock candlestick plotting utility with Chinese font auto-detection.
"""

from .kbar import KBar, detect_font

__all__ = ["KBar", "detect_font"]
__version__ = "0.1.5"


3. 修改版本異動記錄檔 CHANGELOG.md : 

修改為 :

# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),  
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

---

## [0.1.5] - 2025-12-24

### Changed
- 更新依賴,增加上限限制:
  - `numpy>=1.23,<3.0`
  - `pandas>=2.0,<3.0`
  - `matplotlib>=3.7,<4.0`
  - `mplfinance>=0.12.10b0,<1.0`
- 移除對 `pyarrow` 的依賴。
- 修正 `addplot()` 測試錯誤。
- 更新 `README.md` 說明與範例。

---

## [0.1.4] - 2025-11-22

### Changed
- 初版限制:
  - `numpy<2`
  - `pandas<3.0`
  - `matplotlib<4.0`
  - `pyarrow>=14.0.2`

---


4. 清理專案資料夾 & Build 專案 : 

刪除專案資料夾下前次 Build 子目錄 :
  • __pycache__ : 存放 Python 產生的 bytecode 暫存檔的目錄
  • build : 執行 python -m build 生成的中間建構資料夾
  • dist : 上次打包生成的 wheel 與 sdist
  • *.egg-info : setuptools 生成的套件資訊資料夾 (在 src 資料夾下)
用 tree 指令查看是否乾淨 :

D:\PyPi>tree kbar /f  
列出磁碟區 新增磁碟區 的資料夾 PATH
磁碟區序號為 1258-16B8
D:\PYPI\KBAR
│  .gitignore
│  CHANGELOG.md
│  LICENSE
│  pyproject.toml
│  README.md
├─src
│  └─kbar
│          kbar.py
│          __init__.py
└─tests
        test_kbar.py
        __init__.py


5. 打包專案 : 

用 python -m build 指令打包專案 : 

D:\PyPi>cd kbar

D:\PyPi\kbar>python -m build
* Creating isolated environment: venv+pip...
* Installing packages in isolated environment:
  - setuptools>=61.0
  - wheel
* Getting build dependencies for sdist...
C:\Users\tony1\AppData\Local\Temp\build-env-zqe2az72\lib\site-packages\setuptools\config\_apply_pyprojecttoml.py:82: SetuptoolsDeprecationWarning: `project.license` as a TOML table is deprecated
!!
... (略) ...

running install
running install_lib
creating build\bdist.win-amd64\wheel
creating build\bdist.win-amd64\wheel\kbar
copying build\lib\kbar\kbar.py -> build\bdist.win-amd64\wheel\.\kbar
copying build\lib\kbar\__init__.py -> build\bdist.win-amd64\wheel\.\kbar
running install_egg_info
Copying src\kbar.egg-info to build\bdist.win-amd64\wheel\.\kbar-0.1.5-py3.10.egg-info
running install_scripts
creating build\bdist.win-amd64\wheel\kbar-0.1.5.dist-info\WHEEL
creating 'D:\PyPi\kbar\dist\.tmp-j3a6fidi\kbar-0.1.5-py3-none-any.whl' and adding 'build\bdist.win-amd64\wheel' to it
adding 'kbar/__init__.py'
adding 'kbar/kbar.py'
adding 'kbar-0.1.5.dist-info/licenses/LICENSE'
adding 'kbar-0.1.5.dist-info/METADATA'
adding 'kbar-0.1.5.dist-info/WHEEL'
adding 'kbar-0.1.5.dist-info/top_level.txt'
adding 'kbar-0.1.5.dist-info/RECORD'
removing build\bdist.win-amd64\wheel
Successfully built kbar-0.1.5.tar.gz and kbar-0.1.5-py3-none-any.whl

用 tree 指令檢視專案目錄 : 

D:\PyPi\kbar>cd ..  
D:\PyPi>tree kbar /f     
列出磁碟區 新增磁碟區 的資料夾 PATH
磁碟區序號為 1258-16B8
D:\PYPI\KBAR
│  .gitignore
│  CHANGELOG.md
│  LICENSE
│  pyproject.toml
│  README.md
├─dist
│      kbar-0.1.5-py3-none-any.whl
│      kbar-0.1.5.tar.gz
├─src
│  ├─kbar
│  │      kbar.py
│  │      __init__.py
│  │
│  └─kbar.egg-info
│          dependency_links.txt
│          PKG-INFO
│          requires.txt
│          SOURCES.txt
│          top_level.txt
└─tests
        test_kbar.py
        __init__.py

可見已產生打包好的 whl 檔與 gz 原始碼壓縮檔. 


6. 安裝 whl 檔進行發佈前測試 :  

先解除安裝舊版 kbar :

D:\PyPi>pip uninstall kbar   
Found existing installation: kbar 0.1.4
Uninstalling kbar-0.1.4:
  Would remove:
    c:\users\tony1\appdata\local\programs\thonny\lib\site-packages\kbar-0.1.4.dist-info\*
    c:\users\tony1\appdata\local\programs\thonny\lib\site-packages\kbar\*
Proceed (Y/n)? y
  Successfully uninstalled kbar-0.1.4

從 whl 檔安裝新版 v0.1.5 版 kbar : 

D:\PyPi>cd kbar  

D:\PyPi\kbar>pip install dist\kbar-0.1.5-py3-none-any.whl  
Processing d:\pypi\kbar\dist\kbar-0.1.5-py3-none-any.whl
Requirement already satisfied: numpy<3.0,>=1.23 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from kbar==0.1.5) (1.26.4)
Requirement already satisfied: pandas<3.0,>=2.0 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from kbar==0.1.5) (2.3.1)
Requirement already satisfied: matplotlib<4.0,>=3.7 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from kbar==0.1.5) (3.10.5)
Requirement already satisfied: mplfinance<1.0,>=0.12.10b0 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from kbar==0.1.5) (0.12.10b0)
Requirement already satisfied: contourpy>=1.0.1 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from matplotlib<4.0,>=3.7->kbar==0.1.5) (1.3.2)
Requirement already satisfied: cycler>=0.10 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from matplotlib<4.0,>=3.7->kbar==0.1.5) (0.12.1)
Requirement already satisfied: fonttools>=4.22.0 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from matplotlib<4.0,>=3.7->kbar==0.1.5) (4.59.1)
Requirement already satisfied: kiwisolver>=1.3.1 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from matplotlib<4.0,>=3.7->kbar==0.1.5) (1.4.9)
Requirement already satisfied: packaging>=20.0 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from matplotlib<4.0,>=3.7->kbar==0.1.5) (25.0)
Requirement already satisfied: pillow>=8 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from matplotlib<4.0,>=3.7->kbar==0.1.5) (11.3.0)
Requirement already satisfied: pyparsing>=2.3.1 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from matplotlib<4.0,>=3.7->kbar==0.1.5) (3.2.3)
Requirement already satisfied: python-dateutil>=2.7 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from matplotlib<4.0,>=3.7->kbar==0.1.5) (2.9.0.post0)
Requirement already satisfied: pytz>=2020.1 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from pandas<3.0,>=2.0->kbar==0.1.5) (2025.2)
Requirement already satisfied: tzdata>=2022.7 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from pandas<3.0,>=2.0->kbar==0.1.5) (2025.2)
Requirement already satisfied: six>=1.5 in c:\users\tony1\appdata\local\programs\thonny\lib\site-packages (from python-dateutil>=2.7->matplotlib<4.0,>=3.7->kbar==0.1.5) (1.17.0)
Installing collected packages: kbar
Successfully installed kbar-0.1.5

進入 REPL 檢視 kbar 的 __version__ 屬性 : 

d:\PyPi\kbar>python     
Python 3.12.1 (tags/v3.12.1:2305ca5, Dec  7 2023, 22:03:25) [MSC v.1937 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import kbar     
>>> kbar.__version__    
'0.1.5'

用 kbar 繪製 K 線圖 : 

# kbar_test.py
from kbar import KBar   
import yfinance as yf   
df=yf.download('0050.TW', start='2024-07-01', end='2024-08-21', auto_adjust=False)   
df.columns=df.columns.map(lambda x: x[0])    # 改成舊版單層索引
kb=KBar(df)    # 未傳 font 參數預設使用正黑體
kb.plot(title='台灣五十(0050.TW)', volume=True)




7. 發佈到 PyPI 進行升版 :  

利用 twine 套件將專案上傳到 PyPI : 

D:\PyPi\kbar>python -m twine upload dist/*    
Uploading distributions to https://upload.pypi.org/legacy/
Enter your API token:   (按 Ctrl+V 貼上 PyPI API Token 按 Enter )
Uploading kbar-0.1.5-py3-none-any.whl
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 17.2/17.2 kB • 00:00 • ?
Uploading kbar-0.1.5.tar.gz
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 19.2/19.2 kB • 00:00 • ?

View at:




然後到 Pi 3 主機安裝 kbar : 

pi@kaopi3:~ $ pip install kbar
Defaulting to user installation because normal site-packages is not writeable
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting kbar
  Using cached kbar-0.1.5-py3-none-any.whl.metadata (6.1 kB)
Requirement already satisfied: numpy<3.0,>=1.23 in ./.local/lib/python3.9/site-packages (from kbar) (1.26.4)
Requirement already satisfied: pandas<3.0,>=2.0 in ./.local/lib/python3.9/site-packages (from kbar) (2.0.3)
Requirement already satisfied: matplotlib<4.0,>=3.7 in ./.local/lib/python3.9/site-packages (from kbar) (3.9.4)
Requirement already satisfied: mplfinance<1.0,>=0.12.10b0 in ./.local/lib/python3.9/site-packages (from kbar) (0.12.10b0)
Requirement already satisfied: contourpy>=1.0.1 in ./.local/lib/python3.9/site-packages (from matplotlib<4.0,>=3.7->kbar) (1.3.0)
Requirement already satisfied: cycler>=0.10 in ./.local/lib/python3.9/site-packages (from matplotlib<4.0,>=3.7->kbar) (0.12.1)
Requirement already satisfied: fonttools>=4.22.0 in ./.local/lib/python3.9/site-packages (from matplotlib<4.0,>=3.7->kbar) (4.60.2)
Requirement already satisfied: kiwisolver>=1.3.1 in ./.local/lib/python3.9/site-packages (from matplotlib<4.0,>=3.7->kbar) (1.4.7)
Requirement already satisfied: packaging>=20.0 in ./.local/lib/python3.9/site-packages (from matplotlib<4.0,>=3.7->kbar) (25.0)
Requirement already satisfied: pillow>=8 in /usr/lib/python3/dist-packages (from matplotlib<4.0,>=3.7->kbar) (8.1.2)
Requirement already satisfied: pyparsing>=2.3.1 in ./.local/lib/python3.9/site-packages (from matplotlib<4.0,>=3.7->kbar) (3.3.1)
Requirement already satisfied: python-dateutil>=2.7 in ./.local/lib/python3.9/site-packages (from matplotlib<4.0,>=3.7->kbar) (2.9.0.post0)
Requirement already satisfied: importlib-resources>=3.2.0 in ./.local/lib/python3.9/site-packages (from matplotlib<4.0,>=3.7->kbar) (6.5.2)
Requirement already satisfied: pytz>=2020.1 in ./.local/lib/python3.9/site-packages (from pandas<3.0,>=2.0->kbar) (2025.2)
Requirement already satisfied: tzdata>=2022.1 in ./.local/lib/python3.9/site-packages (from pandas<3.0,>=2.0->kbar) (2025.3)
Requirement already satisfied: zipp>=3.1.0 in ./.local/lib/python3.9/site-packages (from importlib-resources>=3.2.0->matplotlib<4.0,>=3.7->kbar) (3.23.0)
Requirement already satisfied: six>=1.5 in /usr/lib/python3/dist-packages (from python-dateutil>=2.7->matplotlib<4.0,>=3.7->kbar) (1.16.0)
Using cached kbar-0.1.5-py3-none-any.whl (7.9 kB)
Installing collected packages: kbar
Successfully installed kbar-0.1.5

少了不需要的 pyarrow 很快就把 kbar 裝好了. 

升版完成收工. 

2025年12月23日 星期二

樹莓派 Pi 3 A+ 燒錄 Bulleye OS

昨天將高雄 Pi 3 改裝 Raspberry Pi OS Bulleye 後順利讓這塊主機滿血復活, 又可以重新投入爬蟲作業了. 我其實是先找一片放了很久的 8GB TF 卡來測試, 成功後把原本的 32GB 卡 (Buster) 改燒 Bulleye, 取下來的 8GB Bulleye 就拿來給 Pi 3A+ 用吧! 之前因為考量它只有 512GB DRAM 跑桌面效能不佳, 所以改燒錄 Trixie Lite 來用, 但沒桌面環境必須透過 ngrok 提供 TCP 連接真的有點麻煩, 參考 :


由於 Pi 3B 與 Pi 3A+ 除了 USB 等介面埠差異外, 硬體上只有 DRAM 容量不同 (1GB vs 512MB) 而已, 所以 TF 卡直接移過去就可以用了, 由於 DRAM 少一半, 用 pip 安裝較大的套件時可能會爆掉, 所以要利用 TF 卡記憶體來分擔暫存區負荷. 

先在使用者根目錄下建立一個 disk_tmp 資料夾 :

pi@pi3aplus:~ $ mkdir -p ~/disk_tmp  

用 nano 編輯 .bashrc 檔 : 

pi@pi3aplus:~ $ nano ~/.bashrc 

在檔案最末端加上如下設定 :

export TMPDIR=~/disk_tmp
export TMP=~/disk_tmp
export TEMP=~/disk_tmp

存檔後跳出 nano, 執行 .bashrc 檔 : 

pi@pi3aplus:~ $ source ~/.bashrc  

由於之前此 8GB TF 卡在 Pi 3B 上就已重新安裝好 numpy 與 pandas, 所以可以直用 : 

pi@pi3aplus:~ $ python  
Python 3.9.2 (default, Mar 20 2025, 22:21:41) 
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pandas as pd  
>>> import numpy as np  
>>> np.__version__  
'1.26.4'
>>> pd.__version__   
'2.0.3'
>>> exit()   

其他可安裝套件與 Pi 3B 一樣, 參考 :


2025年12月22日 星期一

樹莓派 Pi 3 燒錄 Bulleye OS (Debian 11)

月初高雄家裝了光世代後, 高雄這台 Pi 3 主機就連不上新網路, 原因是我之前設定了固定 IP 192.168.2.193, 想改卻因為 X11 視窗異常無法進入終端機, 兩周前乾脆找了一張 TF 卡燒錄 32 位元的新版 Trixie OS, 測試發現Trixie OS 較吃記憶體, 跑 Selenium 爬蟲程式跑了超長的 20 幾分鐘才跑完 (Pi 400 大約 3 分鐘). 我想還是燒錄較舊的 OS 為宜, 就問 AI 在 Bookworm 以前的 Legacy Raspberry Pi OS 是 Buster 嗎? 它回覆是 Bulleye, 於是我去官網下載映像檔來燒錄 :




Bulleye 最後一版是 2025-05-07 發布的, 下載 .xz 檔解壓縮為 .img 檔 :





然後用 Raspberry Pi Imager 軟體選擇自定義映像檔來燒錄 :





注意要選對 drive 為 TF 卡驅動 :







燒錄完畢放入 Pi 3 開機, 依導引做完國家, 語系, 鍵盤, 與 WiFi 設定後重開機, 再用 sudo raspi-config 指令設定 :
  • 開啟 SSH
  • 開啟 VNC Viewer/Server
  • 設定 hostname
完成後重開機, 用 sudo vnclicensewiz 指令或直接按右上角 VNC 圖示登入 VNC Cloud 帳戶以便進行遠端桌面存取. 

先檢查系統與 OS :

pi@kaopi3:~ $ uname -a  
Linux kaopi3 6.1.21-v7+ #1642 SMP Mon Apr  3 17:20:52 BST 2023 armv7l GNU/Linux 
pi@kaopi3:~ $ lsb_release -a  
No LSB modules are available.
Distributor ID: Raspbian
Description: Raspbian GNU/Linux 11 (bullseye)
Release: 11
Codename: bullseye
pi@kaopi3:~ $ cat /etc/issue  
Raspbian GNU/Linux 11 \n \l
pi@kaopi3:~ $ cat /etc/debian_version   
11.11
pi@kaopi3:~ $ cat /etc/os-release   
PRETTY_NAME="Raspbian GNU/Linux 11 (bullseye)"
NAME="Raspbian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"

可見 CPU 為 ARMv71 架構, OS 為代號 Bulleye 的 Raspberry Pi OS (Debian 11.11), 檢查內建 Python 為 3.9.2 版, 應該還不算太舊 : 

pi@kaopi3:~ $ python  
Python 3.9.2 (default, Mar 20 2025, 22:21:41) 
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> exit()   

檢查內建 Python 套件 : 

pi@kaopi3:~ $ pip list  
Package           Version
----------------- ---------
arandr            0.1.10
astroid           2.5.1
asttokens         2.0.4
automationhat     0.2.0
beautifulsoup4    4.9.3
blinker           1.4
blinkt            0.1.2
buttonshim        0.0.2
Cap1xxx           0.1.3
certifi           2020.6.20
chardet           4.0.0
click             7.1.2
colorama          0.4.4
colorzero         1.1
cryptography      3.3.2
cupshelpers       1.0
dbus-python       1.2.16
distro            1.5.0
docutils          0.16
drumhat           0.1.0
envirophat        1.0.0
ExplorerHAT       0.4.2
Flask             1.1.2
fourletterphat    0.1.0
gpiozero          1.6.2
html5lib          1.1
idna              2.10
isort             5.6.4
itsdangerous      1.1.0
jedi              0.18.0
Jinja2            2.11.3
lazy-object-proxy 0.0.0
logilab-common    1.8.1
lxml              4.6.3
MarkupSafe        1.1.1
mccabe            0.6.1
microdotphat      0.2.1
mote              0.0.4
motephat          0.0.3
mypy              0.812
mypy-extensions   0.4.3
numpy             1.19.5
oauthlib          3.1.0
pantilthat        0.0.7
parso             0.8.1
pexpect           4.8.0
pgzero            1.2
phatbeat          0.1.1
pianohat          0.1.0
picamera          1.13
picamera2         0.3.12
pidng             4.0.9
piexif            1.1.3
piglow            1.2.5
pigpio            1.78
Pillow            8.1.2
pip               20.3.4
psutil            5.8.0
pycairo           1.16.2
pycups            2.0.1
pygame            1.9.6
Pygments          2.7.1
PyGObject         3.38.0
pyinotify         0.9.6
PyJWT             1.7.1
pylint            2.7.2
PyOpenGL          3.1.5
pyOpenSSL         20.0.1
PyQt5             5.15.2
PyQt5-sip         12.8.1
pyserial          3.5b0
pysmbc            1.0.23
python-apt        2.2.1
python-prctl      1.7
rainbowhat        0.1.0
reportlab         3.5.59
requests          2.25.1
requests-oauthlib 1.0.0
responses         0.12.1
roman             2.0.0
RPi.GPIO          0.7.0
RTIMULib          7.2.1
scrollphat        0.0.7
scrollphathd      1.2.1
Send2Trash        1.6.0b1
sense-hat         2.6.0
setuptools        52.0.0
simplejpeg        1.6.4
simplejson        3.17.2
six               1.16.0
skywriter         0.0.7
sn3218            1.2.7
soupsieve         2.2.1
spidev            3.5
ssh-import-id     5.10
thonny            4.0.1
toml              0.10.1
touchphat         0.0.1
twython           3.8.2
typed-ast         1.4.2
typing-extensions 3.7.4.3
unicornhathd      0.0.4
urllib3           1.26.5
v4l2-python3      0.3.2
webencodings      0.5.1
Werkzeug          1.0.1
wheel             0.34.2
wrapt             1.12.1

樹莓派 OS 是自下一版 Bookworm 才開始遵循 PEP 668 規範, 因此可以直接用 pip 安裝套件. 由於 Pi 3 主機我主要是拿來當爬蟲用, 爬靜態網頁用的 requests 與 beautifulsoup 都已內建, 但爬動態網頁用的 selenium 卻沒有, 所以先安裝此套件 : 

pi@kaopi3:~ $ pip install selenium   
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting selenium
  Downloading https://www.piwheels.org/simple/selenium/selenium-4.36.0-cp39-cp39-linux_armv7l.whl (3.0 MB)
... (略) ...
Successfully installed attrs-25.4.0 certifi-2025.11.12 exceptiongroup-1.3.1 h11-0.16.0 outcome-1.3.0.post0 pysocks-1.7.1 selenium-4.36.0 sniffio-1.3.1 sortedcontainers-2.4.0 trio-0.31.0 trio-websocket-0.12.2 typing-extensions-4.15.0 urllib3-2.6.2 websocket-client-1.9.0 wsproto-1.2.0

跑 selenium 爬蟲還需安裝 chromium 與其 web driver : 

pi@kaopi3:~ $ sudo apt install -y chromium chromium-driver   
正在讀取套件清單... 完成
正在重建相依關係... 完成  
正在讀取狀態資料... 完成  
The following packages were automatically installed and are no longer required:
  chromium-codecs-ffmpeg-extra libfuse2
Use 'sudo apt autoremove' to remove them.
... (略) ...
設定 chromium-driver (106.0.5249.119-1~deb11u1) ...
執行 man-db (2.9.4-2) 的觸發程式……
執行 mailcap (3.69) 的觸發程式……
執行 fontconfig (2.13.1-4.2) 的觸發程式……
執行 desktop-file-utils (0.26-1) 的觸發程式……
執行 hicolor-icon-theme (0.17-2) 的觸發程式……
執行 gnome-menus (3.36.0-1) 的觸發程式……
執行 libc-bin (2.31-13+rpt2+rpi1+deb11u11) 的觸發程式……

此外爬蟲結果會利用 Telegram 與 LINE 傳送訊息, 所以要安裝 SDK 套件 :

pi@kaopi3:~ $ pip install python-telegram-bot   
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting python-telegram-bot
... (略)...
Requirement already satisfied: typing_extensions>=4.5 in ./.local/lib/python3.9/site-packages (from anyio->httpx<0.29,>=0.27->python-telegram-bot) (4.15.0)
Installing collected packages: httpcore, anyio, httpx, python-telegram-bot
  WARNING: The script httpx is installed in '/home/pi/.local/bin' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Successfully installed anyio-4.12.0 httpcore-1.0.9 httpx-0.28.1 python-telegram-bot-22.5

pi@kaopi3:~ $ pip install line-bot-sdk   
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Requirement already satisfied: line-bot-sdk in ./.local/lib/python3.9/site-packages (3.21.0)
... (略)...

然後將最新版市圖爬蟲程式 ksml_lib_12.py 上傳到 Pi 3, 參考 :


執行結果如下 :

pi@kaopi3:~ $ python ksml_lib_12.py faxxxxxx 5xxxxx  
擷取借閱紀錄 ... OK
擷取預約紀錄 ... OK
產生借書到期摘要 ... OK
產生預約書摘要 ... OK
{'message': 'faxxxxxx 的資料已更新', 'status': 'success'}
執行時間:688.519543170929
pi@kaopi3:~ $ python ksml_lib_12.py 0xxxxx8 9xxxx7   
擷取借閱紀錄 ... OK
擷取預約紀錄 ... OK
產生借書到期摘要 ... OK
產生預約書摘要 ... OK
{'message': '0xxxxx8 的資料已更新', 'status': 'success'}
執行時間:117.28702139854431
pi@kaopi3:~ $ python ksml_lib_12.py 0xxxxx9 8xxxx6  
擷取借閱紀錄 ... OK
擷取預約紀錄 ... OK
產生借書到期摘要 ... OK
產生預約書摘要 ... OK
{'message': '0xxxxx9 的資料已更新', 'status': 'success'}
執行時間:90.50973629951477

借的書越多耗費時間越長 (第一個帳號約 10 分鐘), 但比 Trixie 下要快些了. 

最後上傳母校圖書館爬蟲 :


pi@kaopi3:~ $ python nkust_lib_10.py   
按其他讀者 ... OK
登入系統 ... OK
按名字顯現選單 ... OK
按我的借閱 ... OK
按全部續借 ... OK
搜尋被預約書籍 ... OK
訊息傳送成功!

2025-12-20 21:02:03
被預約的書:
 1. 持續買進 : 資料科學家的投資終極解答, 存錢及致富的實證方法 / 尼克.馬朱利(Nick Maggiulli)著 ; 李芳齡譯 (c.3) 到期日: 12/31/2025
執行時間:401.9524688720703

這樣算是把這片 Pi 3 主機拉回運行軌道了. 


2025-12-22 補充 :

在用 pip 安裝套件時出現如下 warning :

  WARNING: The script wsdump is installed in '/home/pi/.local/bin' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.

消除此警告的方法是執行下列兩個指令 : 

pi@kaopi3:~ $ export PATH=$PATH:/home/pi/.local/bin    
pi@kaopi3:~ $ source ~/.bashrc

其次是內建套件無 pandas, 但有 numpy 1.19.5, 與此 numpy 搭配的是 pandas 1.3.5 :

pi@kaopi3:~ $ pip install pandas==1.3.5  
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting pandas==1.3.5
... (略) ...
Installing collected packages: pytz, python-dateutil, pandas
Successfully installed pandas-1.3.5 python-dateutil-2.9.0.post0 pytz-2025.2

但安裝完匯入 pandas 卻出現錯誤 :

pi@kaopi3:~ $ python  
Python 3.9.2 (default, Mar 20 2025, 22:21:41) 
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pandas as pd   
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/pi/.local/lib/python3.9/site-packages/pandas/__init__.py", line 22, in <module>
    from pandas.compat import (
  File "/home/pi/.local/lib/python3.9/site-packages/pandas/compat/__init__.py", line 15, in <module>
    from pandas.compat.numpy import (
  File "/home/pi/.local/lib/python3.9/site-packages/pandas/compat/numpy/__init__.py", line 7, in <module>
    from pandas.util.version import Version
  File "/home/pi/.local/lib/python3.9/site-packages/pandas/util/__init__.py", line 1, in <module>
    from pandas.util._decorators import (  # noqa
  File "/home/pi/.local/lib/python3.9/site-packages/pandas/util/_decorators.py", line 14, in <module>
    from pandas._libs.properties import cache_readonly  # noqa
  File "/home/pi/.local/lib/python3.9/site-packages/pandas/_libs/__init__.py", line 13, in <module>
    from pandas._libs.interval import Interval
  File "pandas/_libs/interval.pyx", line 1, in init pandas._libs.interval
ValueError: numpy.ndarray size changed, may indicate binary incompatibility. Expected 48 from C header, got 40 from PyObject

解決之道是須先安裝 libatlas-base-dev 套件 :

pi@kaopi3:~ $ sudo apt-get install libatlas-base-dev   
正在讀取套件清單... 完成
正在重建相依關係... 完成  
正在讀取狀態資料... 完成  
The following packages were automatically installed and are no longer required:
  chromium-codecs-ffmpeg-extra libfuse2
Use 'sudo apt autoremove' to remove them.
下列的額外套件將被安裝:
  libatlas3-base
建議套件:
  libatlas-doc liblapack-doc
下列【新】套件將會被安裝:
  libatlas-base-dev libatlas3-base
升級 0 個,新安裝 2 個,移除 0 個,有 0 個未被升級。
需要下載 5,055 kB 的套件檔。
此操作完成之後,會多佔用 26.5 MB 的磁碟空間。
是否繼續進行 [Y/n]? [Y/n] y
下載:1 http://raspbian.raspberrypi.org/raspbian bullseye/main armhf libatlas3-base armhf 3.10.3-10+rpi1 [2,454 kB]
下載:2 http://raspbian.raspberrypi.org/raspbian bullseye/main armhf libatlas-base-dev armhf 3.10.3-10+rpi1 [2,601 kB]
取得 5,055 kB 用了 8s (664 kB/s)                                                            
選取了原先未選的套件 libatlas3-base:armhf。
(讀取資料庫 ... 目前共安裝了 107532 個檔案和目錄。)
正在準備解包 .../libatlas3-base_3.10.3-10+rpi1_armhf.deb……
Unpacking libatlas3-base:armhf (3.10.3-10+rpi1) ...
選取了原先未選的套件 libatlas-base-dev:armhf。
正在準備解包 .../libatlas-base-dev_3.10.3-10+rpi1_armhf.deb……
Unpacking libatlas-base-dev:armhf (3.10.3-10+rpi1) ...
設定 libatlas3-base:armhf (3.10.3-10+rpi1) ...
update-alternatives: 在自動模式下以 /usr/lib/arm-linux-gnueabihf/atlas/libblas.so.3 來提供 /usr/lib/arm-linux-gnueabihf/libblas.so.3 (libblas.so.3-arm-linux-gnueabihf)
update-alternatives: 在自動模式下以 /usr/lib/arm-linux-gnueabihf/atlas/liblapack.so.3 來提供 /usr/lib/arm-linux-gnueabihf/liblapack.so.3 (liblapack.so.3-arm-linux-gnueabihf)
設定 libatlas-base-dev:armhf (3.10.3-10+rpi1) ...
update-alternatives: 在自動模式下以 /usr/lib/arm-linux-gnueabihf/atlas/libblas.so 來提供 /usr/lib/arm-linux-gnueabihf/libblas.so (libblas.so-arm-linux-gnueabihf)
update-alternatives: 在自動模式下以 /usr/lib/arm-linux-gnueabihf/atlas/liblapack.so 來提供 /usr/lib/arm-linux-gnueabihf/liblapack.so (liblapack.so-arm-linux-gnueabihf)
執行 libc-bin (2.31-13+rpt2+rpi1+deb11u13) 的觸發程式……

然後移除內建的 numpy, 重新安裝 numpy 1.19.5 :

pi@kaopi3:~ $ pip3 uninstall -y pandas numpy  
pip3 uninstall -y pandas numpy --user  
sudo apt remove -y python3-numpy python3-pandas   
Found existing installation: pandas 1.3.5 
Uninstalling pandas-1.3.5:
  Successfully uninstalled pandas-1.3.5
Found existing installation: numpy 1.19.5
Uninstalling numpy-1.19.5:
  Successfully uninstalled numpy-1.19.5

Usage:   
  pip3 uninstall [options] <package> ...
  pip3 uninstall [options] -r <requirements file> ...

no such option: --user
正在讀取套件清單... 完成
正在重建相依關係... 完成  
正在讀取狀態資料... 完成  
Package 'python3-numpy' is not installed, so not removed
Package 'python3-pandas' is not installed, so not removed
The following packages were automatically installed and are no longer required:
  chromium-codecs-ffmpeg-extra freeglut3 libfuse2 libglu1-mesa libmikmod3 libportmidi0
  libqt5designer5 libqt5help5 libqt5test5 librtimulib-dev librtimulib-utils librtimulib7
  libsdl-mixer1.2 libsdl-ttf2.0-0 libturbojpeg0 python3-kms++ python3-libcamera
  python3-opengl python3-piexif python3-prctl python3-pyqt5 python3-pyqt5.sip
  python3-rtimulib python3-v4l2
Use 'sudo apt autoremove' to remove them.
升級 0 個,新安裝 0 個,移除 0 個,有 0 個未被升級。

檢查有無殘餘垃圾 & 清理 cache : 

pi@kaopi3:~ $ find ~/.local/lib/python3.9/site-packages/ -name "numpy*" -o -name "pandas*"
pi@kaopi3:~ $ pip cache purge  
Files removed: 6

重新安裝 numpy 與 pandas :

pi@kaopi3:~ $ pip3 install --no-cache-dir "numpy<2.0" "pandas<2.1"  
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting numpy<2.0
  Downloading https://www.piwheels.org/simple/numpy/numpy-1.26.4-cp39-cp39-linux_armv7l.whl (5.6 MB)
Collecting pandas<2.1
  Downloading https://archive1.piwheels.org/simple/pandas/pandas-2.0.3-cp39-cp39-linux_armv7l.whl (38.7 MB)
  Downloading https://www.piwheels.org/simple/tzdata/tzdata-2025.3-py2.py3-none-any.whl (348 kB)
Requirement already satisfied: python-dateutil>=2.8.2 in ./.local/lib/python3.9/site-packages (from pandas<2.1) (2.9.0.post0)
Requirement already satisfied: pytz>=2020.1 in ./.local/lib/python3.9/site-packages (from pandas<2.1) (2025.2)
Requirement already satisfied: six>=1.5 in /usr/lib/python3/dist-packages (from python-dateutil>=2.8.2->pandas<2.1) (1.16.0)
Installing collected packages: tzdata, numpy, pandas
Successfully installed numpy-1.26.4 pandas-2.0.3 tzdata-2025.3

此處指定 numpy 低於 2.0; pandas 低於 2.1 是因為 numpy 2.x 目前在 ARM 舊系統很容易出現衝突錯誤, 而 pandas 2.1+ 則會拉高 numpy 需求, 安裝版本為 numpy-1.26.4 pandas-2.0.3.

測試已可正常匯入 :

pi@kaopi3:~ $ python  
Python 3.9.2 (default, Mar 20 2025, 22:21:41) 
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pandas as pd  
>>> import numpy as np    
>>> pd.__version__  
'2.0.3'
>>> np.__version__  
'1.26.4'

以下整理在 Bulleye OS 下安裝的套件模組, 先更新 pip : 

python -m pip install --upgrade pip  


1. 爬蟲相關 :  

Bulleye 內建的 requests 與 urllib3 太舊, 執行 selenium 會報錯, 需更新 :

pip install --upgrade requests urllib3 
pip install selenium

另外需安裝 chromium 與其 web driver :

sudo apt install -y chromium chromium-driver 

安裝 scrapy 之前須先安裝 libffi-dev 套件, 否則會因缺失 cffi 而失敗 :

sudo apt-get update
sudo apt-get install libffi-dev
pip install scrapy


2. 資料科學 & 機器學習 :  

Bulleye 內建 numpy (無 pandas), 但版本太舊安裝 pandas 會失敗, 先移除 : 

pip uninstall -y numpy
pip uninstall -y numpy --user 
sudo apt remove -y python3-numpy

檢查有無殘餘垃圾 & 清理 cache : 

find ~/.local/lib/python3.9/site-packages/ -name "numpy*" -o -name "pandas*"
pip cache purge

安裝 pandas 要用到的 C 擴充套件 :

sudo apt-get install libatlas-base-dev 

安裝指定版本的 numpy 與 pandas :

pip install --no-cache-dir "numpy<2.0" "pandas<2.1" 

其他套件 : 

pip install seaborn
pip install bokeh
pip install plotly
pip install scikit-learn

註 : scipy 是 scikit-learn 依賴套件, matplotlib 是 gradio 依賴套件


3. 架站套件 :  

Bulleye 已內建 Flask, 但無 Django 與 gradio :

pip install django

在 Bulleye 的 Python 3.9 安裝 gradio 只能到 4.44.1, 無法到最新版, 安裝完須將依賴的 markupsafe 版本降至 2.0.1 與把 huggingface_hub 降至舊版 0.36, 否則匯入 gradio 時會報錯 :  

pip install gradio
pip install markupsafe==2.0.1
python -m pip install "huggingface_hub<1.0" --upgrade --no-cache-dir 

這會安裝 huggingface_hub-1.2.3, 完成後用下列指令檢查是否可正常匯入 :

pi@kaopi3:~ $ python -c "import gradio; print('成功!版本:', gradio.__version__)"   
成功!版本: 4.44.1


4. 量化投資 :

yfinance 雖然可安裝, 但在 Bulleye 上無法搭配 curl_cffi 抓到股票資料, 故放棄安裝. 

pip install yfinance
pip install twstock
pip install mplfinance
pip install ta
pip install kbar
pip install backtrader
pip install pyfolio-reloaded


5. Bot 套件 : 

pip install line-bot-sdk
pip install python-telegram-bot


6. LLM 套件 : 

pip install openai
pip install google-generativeai

除了爬蟲套件以外, 其他都只是測試看看 Bulleye 多舊而已, 備而不用. 

2025 年第 51 周記事

離年尾剩下最後一周了, 我的 Gemini CLI 安裝了一周都還沒搞定, 加油!

週四早上要從鄉下出發上班前才發現爸約 6 點就騎機車出門, 想到前一日在祖堂桌上看到爸買的金香糖果等祭祀用品, 難道今天是水仙王伯公完福嗎? 打電話給容發舅媽詢問爸是否有訂三牲? 果然有訂, 我就開始準備酒杯與麵條等, 然後開始打掃祖堂. 但等到 8 點多爸還沒回來, 想說是否去鎮上買水果, 就先去榮發舅媽家取回三牲, 到 8 點半仍未回來, 查詢手機位置是在阿喜伯家附近, 想必是他記錯日期以為今日伯母要出山, 才打手機叫他回來拜拜. 等收完祭品才出發去上班. 

前陣子去吃楠梓火車站前的正老林羊肉爐覺得還不錯 (每人 600 元), 周末姊姊與二哥回高雄, 我週五晚上去接二哥順路回鄉下, 週六載爸一起去楠梓吃正老林, 這回我幾乎每一項熟食甜點都吃遍啦, 但咖啡除外, 上回喝了一杯晚上失眠. 




週日早上阿喜伯母出山, 我 6 點跟爸一起過去參加告別式, 除了家族親戚外, 也遇到一些以前三合院的鄰居, 現在也只有這種場合才會遇到老鄰舍矣. 坐遊覽車送往火葬場途中, 看見山邊裊裊的幾縷輕煙, 頓覺人生似乎就像這樣. 



 
很久以前預計要在鄉下廚房裝一個太陽能燈, 這樣太陽下山後廚房就會自動有光, 我上週已在頂樓將太陽能板鎖在女兒牆上, 剩下拉線與廚房燈座安裝, 這周因事情較多沒空, 下周再進行 : 





昨晚本想寫周記, 但實在太睏了只好放棄, 但睡前卻發現部落格累積到訪人數破千萬, 我以為 AI 時代谷歌搜尋會褪色, 沒想到還是很多流量來自谷歌搜尋找到我這本雜記簿 : 




月初二哥說他 IC 資料上傳後時間很空, 問說要不要去參觀故宮百年展, 原本想與水某搭高鐵去, 菁菁說她元旦可以排假也想去, 姊姊也說她也沒節目, 於是決定開車去台北, 順路去宜蘭玩. 本周我訂好住宿會館 (板橋 & 蘇澳) 也匯款完成了, 下周要來規劃交通與行程. 

2025年12月19日 星期五

蝦皮購買 USB 1080P Webcam x 2

為了在樹莓派測試 opencv/mediapipe 需要, 今天上蝦皮向賣家 777nice 買了兩個 webcam :






裕誠智取店免運共 311 元. 

PS: 因為上回在露天買小米攝影機 c200 賣家寄來不知名中國雜牌仿小米爛貨, 聯絡賣家換貨遲不寄貨, 被我判定為準 (軟性) 網購詐騙賣家, 聯絡露天要求處理未果, 現在露天被我視為軟詐騙賣家集中營, 非必要不在露天交易. 網購優先找 momo, 其次是退換貨機制較好的蝦皮, 露天只跟之前交易過的優良賣家交易. 


2025-12-25 補充 :

上週四到貨, 今天聖誕節放假帶回鄉下測試, 一插上 USB Win10 就偵測自動安裝完成, 按 Win+R 搜尋裝置管理員, 可看到相機已就緒 :




瀏覽器開啟 Google Meet 發起一個會議, 可正常看到影像 :




可見此賣家 webcam 品質 OK, 接下來測試樹莓派, 如果能抓到驅動程式正常攝影就再多買幾個. 

2025年12月16日 星期二

河堤單車練騎

我這兩天開始了單車練騎, 昨天沿河堤往鼓山方向騎, 本想騎到愛河去看看聖誕節裝飾, 但騎到中華路過去老新台菜前面, 因為修路無法通行只好折返, 單程約 3.8km :





今天則是沿河堤往北騎, 騎到博愛路巨蛋附近折返, 單程約 3.2km :





打算每周一, 二, 四下班沒事就來鍛鍊, 我想在一月中旬騎到墾丁去, 到恆春住一晚第二天折返. 已經快三十年沒騎長途了, 先暖身一下, 明年春天就直接騎到台東, 再從南橫回西部. 

2025年12月14日 星期日

2025 年第 50 周記事

2025 剩下兩周啦! 原本年底前想把 LINE Bot 的學習結束掉, 卻被學習 Vibe coding (Claude Code & Gemini CLI) 打斷, 恐怕要 Hold 住, 等明年第一季之後再繼續了. 寫程式真的太勞心了, 應該讓近乎全能的 AI 來幫我們做底層勞動才對, 以後的軟體工程師要站在系統思維角度來作專案, 把時間花在更有價值的創新功能思考上才對. 

我現在週三下班都會回鄉下, 主要是檢視冰箱的蔬菜肉品, 讓煮菜的居服員周四周五兩天能使用. 週三晚上繞曬穀場快走時, 瞥見一條蛇從龍眼樹下游向車庫, 四隻好奇的小貓圍過去一探究竟, 我趕緊驅離小貓, 拿起牆邊掃把朝蛇頭猛敲, 才三兩下那蛇就不動了, 用掃把柄將它掛起來, 丟到馬路對面休耕的田裡以免小貓去探查, 因為我也不確定蛇是否 GG 了. 





我拍下照片傳給見多識廣的國中同學信宏, 他認為是眼鏡蛇, 叫我拍它腹部照片給他看看, 我說已丟到田裡了. 第二天上班前拿鏟子去對面田裡尋找, 發現蛇真的死了, 於是念過往生咒後挖了個洞將蛇埋了, 埋之前拍了它腹部照片傳給同學, 確認是中華眼鏡蛇 :




週六晚上接到秀滿阿姨電話, 說阿喜伯母前日往生, 我早上載爸過去捻香, 我一大早也將這訊息轉給堂哥與嬸嬸. 上完香不久就看到堂哥與堂嫂也來了, 商量了一下便決定不送花, 兩人聯名送米塔. 伯母一走, 我們家族長輩就僅阿喜伯, 爸, 與阿信叔嬸四人了, 我也老之將至矣, 幾位堂妹也是自小五我們家搬離三合院之後近五十年再次相見, 與兒時記憶相比, 只能說歲月不饒人啊! 她們看我也是如此吧? 看訃聞出山日期為周日, 剛好假日無須請假. 

鄉下家八隻貓的鼻祖貓婆婆小灰自從九月初毛小妹生了四隻小貓仔后, 便開始離家 (似乎把家主位置交給女兒毛小妹), 偶而才會回來吃乾糧 (通常是晚上或半夜). 週日下午她又回來吃貓糧, 吃完就越過田與馬路, 消失在荒野中 :






因為不知道她下一次何時會回家, 所以我就跟蹤她到對面的田裡, 偷拍了幾張照片. 

最近高麗菜很便宜, 加上小舅在我家菜園種的胡瓜吃不完, 我上週乾脆拿來做高麗菜封, 順便把冰箱的豬肉消耗掉, 菁菁週日晚上回家時看到我帶回高雄的高麗菜封還是熱的, 拿來當晚餐吃, 說好久沒吃到這美味了, 所以本周特地在全聯買了三盒雞肉再次做燜高麗菜 :




小阿姨當年下來高雄開燒臘店時用的這口大鍋真好用, 拿來燜高麗菜剛剛好. 

蝦皮購買 Tuya 小圓智能插座 5 個 (增購)

我在 2022 年底曾在蝦皮買過 Tuya 小圓智能插座, 目前剩下 2 個將用罄, 向此賣家再買 5 個 20A 無計量 3 孔 2 插 :






自由路智取店取付. 

2025年12月13日 星期六

在 Windows 上安裝原生版 Claude Code

最近與明賢表弟在 LINE 上聊到 Vibe coding, 他今年用 Claude Code 開發軟體的經驗是, 以後程式員都得放棄自行 coding 的想法, 因為 AI 寫程式的能力太強, 軟體工程師都應轉型為具有系統思維的 PM. 這讓我對 Claude Code 突然有了興趣, 在 momo 買了市面上僅有的兩本書來一探究竟 : 


今天先把 Claude Code 開發環境架起來, 主要參考旗標這本書, 在 LG Gram 筆電上透過 Scoop 軟體從網路下載 PowerShell 腳本程式安裝原生版 Cloude Code, 步驟如下 : 


1. 設定 PowerShell 視窗腳本執行原則 (Execution Policy) : 

首先在 Windows 搜尋 powershell 並直接開啟此視窗程式 (不要用系統管理員), 然後複製貼上下列指令按 Enter 執行, 這樣才能執行從網路下載具有數位簽章的 PowerShell 腳本程式 Scoop :

PS C:\Users\tony1> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser  
PS C:\Users\tony1>




書上說會出現 Yes/No 詢問提示, 但我的沒有, 這可能是 -Scope CurrentUser 的關係, 這表示變更範圍只影響目前使用者, 不會影響到系統上的其他使用者或整個電腦, 所以 PowerShell 有時會省略提示, 直接接受對當前使用者設定的修改. 


2. 安裝套件管理工具 Scoop : 

貼上下列指令從網路下載 Scoop 腳本執行安裝 :

PS C:\Users\tony1> Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression   
Initializing...
Downloading...
Extracting...
Creating shim...
Adding ~\scoop\shims to your path.
Scoop was installed successfully!
Type 'scoop help' for instructions.


3. 安裝 Git 與設定 git-bash 環境變數 : 

使用 Scoop 來安裝 Git : 

PS C:\Users\tony1> scoop install git   
Scoop uses Git to update itself. Run 'scoop install git' and try again.
Installing '7zip' (25.01) [64bit] from 'main' bucket
7z2501-x64.msi (1.9 MB) [====================================================] 100%
Checking hash of 7z2501-x64.msi ... ok.
Extracting 7z2501-x64.msi ... done.
Linking ~\scoop\apps\7zip\current => ~\scoop\apps\7zip\25.01
Creating shim for '7z'.
Creating shim for '7zFM'.
Making C:\Users\tony1\scoop\shims\7zfm.exe a GUI binary.
Creating shim for '7zG'.
Making C:\Users\tony1\scoop\shims\7zg.exe a GUI binary.
Creating shortcut for 7-Zip (7zFM.exe)
Persisting Codecs
Persisting Formats
Running post_install script...done.
'7zip' (25.01) was installed successfully!
Notes
-----
Add 7-Zip as a context menu option by running:
reg import "C:\Users\tony1\scoop\apps\7zip\current\install-context.reg"
Installing 'git' (2.52.0) [64bit] from 'main' bucket
PortableGit-2.52.0-64-bit.7z.exe (57.4 MB) [=================================] 100%
Checking hash of PortableGit-2.52.0-64-bit.7z.exe ... ok.
Extracting PortableGit-2.52.0-64-bit.7z.exe ... done.
Linking ~\scoop\apps\git\current => ~\scoop\apps\git\2.52.0
Creating shim for 'sh'.
Creating shim for 'bash'.
Creating shim for 'git'.
Creating shim for 'gitk'.
Making C:\Users\tony1\scoop\shims\gitk.exe a GUI binary.
Creating shim for 'git-gui'.
Making C:\Users\tony1\scoop\shims\git-gui.exe a GUI binary.
Creating shim for 'scalar'.
Creating shim for 'tig'.
Creating shim for 'git-bash'.
Making C:\Users\tony1\scoop\shims\git-bash.exe a GUI binary.
Creating shortcut for Git Bash (git-bash.exe)
Creating shortcut for Git GUI (git-gui.exe)
Running post_install script...done.
'git' (2.52.0) was installed successfully!
Notes
-----
Set Git Credential Manager Core by running: "git config --global credential.helper
manager"

To add context menu entries, run
'C:\Users\tony1\scoop\apps\git\current\install-context.reg'

To create file-associations for .git* and .sh files, run
'C:\Users\tony1\scoop\apps\git\current\install-file-associations.reg'

注意, 此處安裝 Git 並非是要用到版本控制, 而是要利用 Git 所附的 git-bash 來執行 Claude Code. 用 where.exe 查詢 bash 程式位置 (若有多個要找路徑中含有 scoop 者) : 

PS C:\Users\tony1> where.exe bash
C:\Users\tony1\scoop\shims\bash.exe
PS C:\Users\tony1>

先將 git-bash 路徑複製下來, 按搜尋鈕輸入 "環境變數" :




新增使用者變數 CLAUDE_CODE_GIT_BASH_PATH :




貼上前面複製的 git-bash 路徑 : 




按確定完成設定 :




關閉 Power Shell 視窗重開, 這樣新增的環境變數才會生效. 以上設定是因為 Claude Code 固定會到環境變數 CLAUDE_CODE_GIT_BASH_PATH 去找 git-bash 路徑之故. 


4. 安裝原生版 Claude Code : 

在重新開啟的 Power Shell 視窗輸入下列指令安裝 Claude Code  :

PS C:\Users\tony1> irm https://claude.ai/install.ps1 | iex   
Setting up Claude Code...

√ Claude Code successfully installed!

  Version: 2.0.65

  Location: C:\Users\tony1\.local\bin\claude.exe


  Next: Run claude --help to get started

‼ Setup notes:
  • Native installation exists but C:\Users\tony1\.local\bin is not in your PATH. Add it by opening: System Properties →
   Environment Variables → Edit User PATH → New → Add the path above. Then restart your terminal.


✅ Installation complete!


這樣便安裝好 Claude Code 了, 在 Setup notes 中提醒要將 Claude Code 的執行檔路徑加入使用者環境變數 Path 中, 這樣以後才能在任何路徑下執行 Claude Code, 設定方式與上面設定環境變數 CLAUDE_CODE_GIT_BASH_PATH 相同, 點選使用者變數 Path 按編輯鈕 :




按新增鈕 : 




貼上 Claude Code 程式路徑 C:\Users\tony1\.local\bin 後按確定即可 :




以上便完成 Claude Code 安裝與設定了.

關閉 Power Shell 視窗重開, 下 claude 指令即可啟動 Claude Code : 

PS C:\Users\tony1> claude 




按上下鍵選擇一個終端機樣式, 直接按 Enter 使用預設 Dark mode 即可. 接下來會進入登入頁面並要求選擇一個付費方案 (Pro/Max), 這部分先 hold 一下, 後續要使用時再來設定. 接下來先用 scoop 安裝其他會用到的軟體. 

2025年12月11日 星期四

在樹莓派 Pi 400 上執行 Streamlit 應用程式

我的 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/ :




這樣就可以從公網存取這個本機網站了.