2023年4月30日 星期日

2023 年第 18 周記事

本周菁菁說她周日排休息, 所以週六想跟我回鄉下, 但要傍晚才能結束工作, 所以我週六整天都在高雄忙字集排列的程式, 等菁菁回來才出發, 回到鄉下老家已晚上九點. 下班前喜孜孜打電話跟我說有兩個好消息, 其一是四月份收入已突破 6 萬, 覺得換到楠梓三信學姊那邊開工作室比在鳥松還好 (只是比較遠, 且要兩三天才回家一次). 其二是有客人要向她拜師學美睫, 所以今天一整個下午都在打講義. 我原先以為美睫師大概只能當副業, 沒想到她當主業還忙到要排時間休息. 

今天下午在屋後給芒果套袋時, 爸過來說頂樓兩個水塔都沒水, 水龍頭打開都沒水, 我到頂查查看確實是空桶, 趕緊打電話問台水是否有停水, 回覆說都正常, 要我們檢查幫浦, 但到張家伙房門口查看水表都沒在轉, 開關怎麼轉都轉不動, 水公司人員說可能止水閥有問題, 但因為 5/1 勞動節可能要周二才能派員查修, 哇, 這不就兩天沒水用? 只好去開啟馬達開關抽屋後水池的水上去頂樓左東側水塔應急, 但抽了十分鐘還是沒水, 我打開水池蓋一看, 哇, 備用水池也是空的, 太久沒引水來儲備了. 無奈只好拿鋤頭去清水圳, 因為大圳水量不豐, 進水圳後的薄水會被淤泥阻塞無法通行. 吃過飯後戴頭頂燈去查看, 水池已 2/3 滿了. 這件事讓我下定決心要加快速度完成居家物聯網建置作業, 水塔水位監測列第一優先.  

本周在 Netflix 看完韓劇 "造后者", 描寫金喜愛飾演的黃導囍如何將人權律師吳景淑推上首爾市長寶座, 劇中主要描述豪門財團銀星集團會長孫迎心為了企業利益, 強推女婿白宰民競選市長補選, 在選戰建豐富的卡爾尹當助下, 與另一陣營候選人勞工人權律師吳景淑在選戰中短兵相爭的故事, 而吳律師的競選總幹事則是剛被銀星集團免職的戰略企劃室長黃導囍, 劇名造后者指的就是處事果斷精明幹練的黃導囍. 此劇揭露了政治人物為了權力與利益而喪失人性的醜陋, 但也有人是像吳景淑那樣堅持理想絕不向惡勢力妥協, 黃導囍因為處理勞資爭議而與吳景淑認識, 第一印象非常糟糕, 但黃導囍因為韓以瑟墜樓事件被逐出銀星集團, 原先是為了復仇而加入吳景淑陣營, 但隨著選戰開打, 她也在考驗中找回了人性的溫暖, 她雖是造后者, 但其實也是被救贖的人, 此劇非常值得一看. 

好書 : C & C++ 程式設計經典 (第五版)

最近為了 C 語言備課從市圖借了幾本 C 語言的書, 其中下面這本我翻閱後覺得編得真不錯, 難怪匯出到第五版 (聽說是補習班教程式語言的指定教科書) :



Source : 博客來


此書前 2/3 以 C 語言的用法為主, 後半部講物件導向與樣版等主題時才改用 C++ 語法, 每一章最後面一節為實例, 以數個程式範例說明如何利用該章主題所介紹的功能解決實際問題. 我原本認為學會 C 語言可以用在 Arduino IDE 的應用上應該就夠了, C++ 我根本沒興趣. 但看著看著覺得 C++ 還蠻有趣的, 能趁這機會學起來也不錯. 

書中範例程式可從碁峰網站下載 :


2023年4月27日 星期四

好用的 TinyML 整合開發平台 Edge Impulse

今天上 AIoT 內訓課程還挖到一個寶 : Edge Impulse, 這是一個成立於 2019 年的 TinyML 整合開發平台, 提供 AIoT 應用一站式雲端解決方案, 只要透過瀏覽器即可完成資料集收集, 模型建置與訓練, 參數調整測試, 以及模型佈署四大步驟, 目前平台上已有近 15 萬個專案, 參考 : 


Edge Impulse 支援各種開發板 (目前 25 種), 參考 :  


其中包含了性價比極高, 廣為物聯網 Maker 使用的 ESP32 與 Raspberry Pi RP2040 等. 

申請 Edge Impulse 帳戶可連線官網首頁 : 


按右上角的 "Get started" 鈕可註冊帳戶 : 




輸入姓名, 帳號, email, 密碼, 勾選隱私權聲明按 "Sign up" 鈕即可 :




這時到信箱收註冊確認信, 按信中的確認網址會開啟 Edge Impulse 登入頁面 : 






輸入 email 與密碼登入即完成註冊 : 




按底下紅色按鈕會進入 studio.edgeimpulse.com 網站開始建構專案, 剛開始會用一個語音辨識專案來展示如何在五分鐘內建立專案 : 




在中間輸入框填入要辨識的文字, 例如 Hello Tony :




接下來的頁面要錄音, 在 38 秒內每隔 1 秒念 Hello Tony, 錄完後會上傳到 Edge Impulse 平台 : 





接下來是上傳背景雜音 :





然後是對語音資料進行 impulse (語音識別 + 模型訓練), 首先是提取聲譜 (spectrogram) :




接著提取特徵 (feature) : 




第七步是訓練模型 : 




接著是將專案的模型佈署到平台上 :






佈署成功後執行專案, 即評估此模型的效果, 這會要求授予存取麥克風權限 : 




按右下方 Next, check out next steps 鈕開始錄音, 底下會顯示 Hello Tony, Noise, 以及 UNKNOWN 的辨識機率, 當念 Hello Tony 時左方的 Hello Tony 辨識機率就會提高, 反之就很低 : 





以上展示了快速完成一個語音辨識專案的步驟. 

Edge Impulse 提供免費與企業付費方案, 參考 : 





Arduino Portenta 開發板

今天在 AIoT 內訓課程中得知 Arduino 有一款可執行 AI 邊緣計算的板子 Portenta, 隨手到露天查詢發現價格不便宜, 要八千多塊 : 





硬體上 MCU 採用 STM32H747 (ARM Cortex M4 + M7 雙核, 內建 GPU, 具備 JPEG 編解碼器), 16MG Flash, 8MB SDRAM, 內建 WiFi 與藍牙連網能力, GPIO 提供 UART/SPI/I2C 通信埠, 可執行 MicroPython, Javascript, 與 TensorFlowLite 機器學習運算, 工作電壓 3.3V, 可用 700 mAH 鋰電池供電. 這配備真的很不錯, 但是太貴了.
 

2023年4月24日 星期一

露天購買捕蚊燈 RASTO AZ5

由於最近鄉下家的廚房廚餘桶出現很多小飛蟲, 上週去美泰買了一個  RASTO AZ5 紫外線捕蚊燈, 價格為 990 元, 此款為 15W 功耗, 上面有一個按鈕開關, 回來測試確實可捕捉到一些蚊蟲. 但查露天卻發現建國路復興路口的太極數位賣 788 元 : 


因高雄也需要一個, 電詢可自取, 但上週五去電裡卻剛好缺貨要調, 週日通知有貨了, 今天下班順路去取貨. 跟鄉下買的差了 100 多塊, 買之前還是要上網比價一下為好.

Node-RED 學習筆記 : 安裝(更新) Node.js

上週四參加 MQTT 社團益師傅的 Node-RED 新手入門 Team 線上講座, 這是一個 hands-on 課程, 但要在 Team 與 Node-RED 之間切換畫面我怕跟不上就專心聽講, 然後課後再重看錄影實作. 今天上第二堂課, 主題是 3.1 版新功能與 MQTT 實作, 這次我打算用 Ideal-Pad 筆電聽課, 用 Swift5 來實作, 但發現我的 Node.js 版本較舊, 且第一堂我也還沒複習, 所以就趁空檔更新 Node.js.

我很早之前就安裝了 Node.js, 學了一點點就沒空學了. 後來持續更新到 v17.3 :

C:\Users\User>node   
Welcome to Node.js v17.3.1.
Type ".help" for more information.

目前 Node.js 最新版本是 v20.0, 穩定版本是 v18.6, 只要更新到穩定版即可. 更新版本不需要移除舊版本, 直接下載安裝新版本即可 (Windows), 基本上照預設按確定即可 : 








這一步預設沒有勾選, 若勾選則 Node.js 安裝完成後會用自動開啟 Powershell 安裝其他工具 (例如 Python 與 Visual Studio 2019 等, 建議不要勾選).





由於上面有勾選安裝其他工具, 所以按 Finish 後開啟 Powershell 視窗自動安裝這些工具, 連 Python 都被提升到 v3.11.3 (這下常用套件得重新安裝了, 但 Ta-Lib 可能無法安裝了, 它目前只到 3.10), 但 Visual Studio 開發工具安裝途中出現錯誤 : 





安裝完檢查 Python 已安裝最新版的 v3.11.3 :

C:\Users\User>python   
Python 3.11.3 (tags/v3.11.3:f3909b8, Apr  4 2023, 23:49:59) [MSC v.1934 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> exit()  

Node.js 提升到 v18.16 : 

C:\Users\User>node   
Welcome to Node.js v18.16.0.
Type ".help" for more information. 

2023 年第 17 周記事

本周因為執行政策的關係工作仍然忙碌, 還好沒有吸引我興趣的內訓 (機器學習, NLP, ChatGPT 等) 衝到. 但進入四月下旬, 最近要開始為下月底的授課準備, 最近隨身的書籍改成 C++. 

鄉下老家的喵星族四兄弟在三月底時陸續離家, 連從不離家的毛小咪也已一周未回, 可能是發情期到了在外拚事業. 斷尾的喵老三則沒那麼樂觀, 最糟是傷口發炎回不來了. 噪咖喵老二上周有回, 但本周不確定, 因為他們三兄弟毛色太像, 爸也分不清回來的是誰. 周末這兩天喵老大早晚都有回來吃飯, 他們兄弟回來時都會在曬穀場喵喵叫, 意思是我回來了要吃飯, 吃完喝口水又跑出大門去拚事業, 叫它還會停下來回頭看看, 好像聽得懂似的. 昨晚喵老大吃飽躺在曬穀場中央陪爸騎單車, 感覺好溫馨 :





好懷念它們四兄弟趴在矮牆上陪騎的日子. 前天滑臉書的時候迸出一張我 11 年前發布的動態回顧照片, 這是鄰居印尼新娘送給媽養的三隻貓中的大咪 :




它睡在放農具的矮桌上, 旁邊是媽剛摘下來的胡瓜, 當時拍下後順手就上傳到剛啟用的臉書. 它這毛色感覺跟毛小咪好像啊! 大咪後來有一天也是外出後沒回來了. 所以放養的家貓最好是要結紮, 否則八個月大後發情期就會離家了.

週五打電話給社區發展協會詢問給爸送餐事宜, 可送午晚餐, 費用下周才會告知. 目前我每周煮好放冰箱, 但冷凍的比不上送餐新鮮, 且蔬菜類也不適合冷凍. 還在想午晚都送還是先只送午餐, 前者我周末就不用把時間全花在料理, 但兩餐都吃便當似乎又太膩. 

阿蘭往生兩周矣, 我每週日早上去市場後順路拿金香去觀音廟上香, 頌往生咒迴向. 

周末兩天繼續給芒果套袋, 週日又去農資行買了兩包, 現在累積已用掉 9 包, 估計套了 900 顆以上, 史無前例, 以前豐收時頂多 700~800 顆. 週日踩高梯套比較高的, 總算把能套的幾乎套完了, 剩下路邊還有一些零星的, 下周就可收尾了. 

2023年4月22日 星期六

Win10 設定開機自動登入的方法

最近幾天無法遠端連線鄉下老家的那台 Windows 電腦, 中午回鄉下發現原來是不明原因重開機, 停在登入畫面所致. 每次遇到這種情形只能等周末回去處理很麻煩, 爬文發現其實只有個人使用的電腦可以設定為自動登入, 參考 : 


方法是在開始的 "Windows 系統" 點選 "執行", 輸入 regedit 後按確定 :





這樣會開啟登錄表, 點選 "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\PasswordLess\Device\DevicePasswordLessBuildVersion" 這個項目, 可看到其預設值為 2, 此表示開機時須登入 :




點擊此項目兩下會進入設定頁面, 將設定值改為 0 : 




然後再次於開始的 "Windows 系統" 點選 "執行", 輸入 netplwiz 後按確定 :




這樣會開啟 "使用者帳戶" 頁面 : 




將上方的 "必須輸入使用者名稱和密碼才能使用這台電腦" 取消勾選, 這會跳出一個 "自動登入" 頁面, 輸入該帳號的登入密碼按確定即可 :




這樣下次重開機時就會自動登入系統, 不需要再輸入密碼了. 

註 : Win10 的使用者帳戶頁面預設不會顯示 "必須輸入使用者名稱和密碼才能使用這台電腦" 這個勾選項目, 這是因為登錄表的 "DevicePasswordLessBuildVersion" 項目預設為 2 的緣故, 前面將其改為 0 就是要讓這個項目顯示出來, 這樣我們才能取消它. 

2023年4月19日 星期三

在 Linux Mint 上安裝新版 Python 3 的問題

下午更新完 Acer D255 小筆電的 Linux Mint 後在終端機輸入 python  結果是進入 Python 2.7, 而輸入 python3 指令則是進入 Python 3.5.2 解譯器 :

tony1966@tony1966-AOD255 ~ $ python3   
Python 3.5.2 (default, Jan 26 2021, 13:30:48)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.

v.3.5 真的有點舊了, 有些好用功能不能用, 例如最近發現 math.perm() 與 math.comb() 要 3.8 版以後才支援, 所以最好能將 Python 版本提升到最新版. 我找到下面的教學文章 : 

 
我依照指引嘗試安裝 3.11 與 3.10 都因套件清單找不到這兩個版本, 降至 3.9 版就有了, 但安裝完成後卻沒在 /usr/bin 底下找到 Python3.9, 好奇怪, 先將安裝過程記錄下來, 明天有空再找看看是何原因 :


1. 更新套件清單與升版套件 :

tony1966@tony1966-AOD255 ~ $ sudo apt update
tony1966@tony1966-AOD255 ~ $ sudo apt upgrade

這兩個指令在稍早的那篇文章已做過, 參考 : 



2. 安裝必要之套件 :

中間會停下來詢問是否要繼續安裝, 輸入 y : 

tony1966@tony1966-AOD255 ~ $ sudo apt install wget build-essential libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev libffi-dev zlib1g-dev 
Reading package lists... Done
Building dependency tree       
Reading state information... Done
libc6-dev is already the newest version (2.23-0ubuntu11.3).
wget is already the newest version (1.17.1-1ubuntu1.5).
The following additional packages will be installed:
  g++ g++-5 libexpat1-dev libfontconfig1-dev libfreetype6-dev libice-dev libpng12-dev libsm-dev libstdc++-5-dev libtinfo-dev
  libxext-dev libxft-dev libxrender-dev libxss-dev libxt-dev tcl-dev tcl8.6-dev tk8.6-dev x11proto-render-dev
  x11proto-scrnsaver-dev x11proto-xext-dev
Suggested packages:
  g++-multilib g++-5-multilib gcc-5-doc libstdc++6-5-dbg libice-doc ncurses-doc libsm-doc sqlite3-doc libstdc++-5-doc
  libxext-doc libxt-doc tcl-doc tcl8.6-doc tk-doc tk8.6-doc
Recommended packages:
  bzip2-doc libssl-doc
The following NEW packages will be installed:
  build-essential g++ g++-5 libbz2-dev libexpat1-dev libffi-dev libfontconfig1-dev libfreetype6-dev libgdbm-dev libice-dev
  libncursesw5-dev libpng12-dev libsm-dev libsqlite3-dev libssl-dev libstdc++-5-dev libtinfo-dev libxext-dev libxft-dev
  libxrender-dev libxss-dev libxt-dev tcl-dev tcl8.6-dev tk-dev tk8.6-dev x11proto-render-dev x11proto-scrnsaver-dev
  x11proto-xext-dev zlib1g-dev
0 upgraded, 30 newly installed, 0 to remove and 4 not upgraded.
Need to get 16.7 MB of archives.
After this operation, 69.7 MB of additional disk space will be used.
Do you want to continue? [Y/n] y   
Get:1 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 libstdc++-5-dev amd64 5.4.0-6ubuntu1~16.04.12 [1428 kB]
Get:2 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 g++-5 amd64 5.4.0-6ubuntu1~16.04.12 [8430 kB]
Get:3 http://archive.ubuntu.com/ubuntu xenial/main amd64 g++ amd64 4:5.3.1-1ubuntu1 [1504 B]                                 
Get:4 http://archive.ubuntu.com/ubuntu xenial/main amd64 build-essential amd64 12.1ubuntu2 [4758 B]                          
Get:5 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 libbz2-dev amd64 1.0.6-8ubuntu0.2 [29.0 kB]                 
Get:6 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 libexpat1-dev amd64 2.1.0-7ubuntu0.16.04.5 [115 kB]         
Get:7 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 zlib1g-dev amd64 1:1.2.8.dfsg-2ubuntu4.3 [167 kB]           
Get:8 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 libpng12-dev amd64 1.2.54-1ubuntu1.1 [183 kB]               
Get:9 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 libfreetype6-dev amd64 2.6.1-0.1ubuntu2.5 [955 kB]          
Get:10 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 libfontconfig1-dev amd64 2.11.94-0ubuntu1.1 [658 kB]       
Get:11 http://archive.ubuntu.com/ubuntu xenial/main amd64 libgdbm-dev amd64 1.8.3-13.1 [35.9 kB]                             
Get:12 http://archive.ubuntu.com/ubuntu xenial/main amd64 libice-dev amd64 2:1.0.9-1 [44.9 kB]                               
Get:13 http://archive.ubuntu.com/ubuntu xenial/main amd64 libtinfo-dev amd64 6.0+20160213-1ubuntu1 [77.4 kB]                 
Get:14 http://archive.ubuntu.com/ubuntu xenial/main amd64 libncursesw5-dev amd64 6.0+20160213-1ubuntu1 [198 kB]              
Get:15 http://archive.ubuntu.com/ubuntu xenial/main amd64 libsm-dev amd64 2:1.2.2-1 [16.2 kB]                                
Get:16 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 libsqlite3-dev amd64 3.11.0-1ubuntu1.5 [509 kB]            
Get:17 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 libssl-dev amd64 1.0.2g-1ubuntu4.20 [1347 kB]              
Get:18 http://archive.ubuntu.com/ubuntu xenial/main amd64 x11proto-xext-dev all 7.3.0-1 [212 kB]                             
Get:19 http://archive.ubuntu.com/ubuntu xenial/main amd64 libxext-dev amd64 2:1.3.3-1 [82.1 kB]                              
Get:20 http://archive.ubuntu.com/ubuntu xenial/main amd64 x11proto-render-dev all 2:0.11.1-2 [20.1 kB]                       
Get:21 http://archive.ubuntu.com/ubuntu xenial/main amd64 libxrender-dev amd64 1:0.9.9-0ubuntu1 [24.5 kB]                    
Get:22 http://archive.ubuntu.com/ubuntu xenial/main amd64 libxft-dev amd64 2.3.2-1 [45.7 kB]                                 
Get:23 http://archive.ubuntu.com/ubuntu xenial/main amd64 x11proto-scrnsaver-dev all 1.2.2-1 [25.0 kB]                       
Get:24 http://archive.ubuntu.com/ubuntu xenial/main amd64 libxss-dev amd64 1:1.2.2-1 [12.7 kB]                               
Get:25 http://archive.ubuntu.com/ubuntu xenial/main amd64 libxt-dev amd64 1:1.1.5-0ubuntu1 [394 kB]                          
Get:26 http://archive.ubuntu.com/ubuntu xenial/main amd64 tcl8.6-dev amd64 8.6.5+dfsg-2 [882 kB]                             
Get:27 http://archive.ubuntu.com/ubuntu xenial/main amd64 tcl-dev amd64 8.6.0+9 [5664 B]                                     
Get:28 http://archive.ubuntu.com/ubuntu xenial/main amd64 tk8.6-dev amd64 8.6.5-1 [682 kB]                                   
Get:29 http://archive.ubuntu.com/ubuntu xenial/main amd64 tk-dev amd64 8.6.0+9 [2964 B]                                      
Get:30 http://archive.ubuntu.com/ubuntu xenial/main amd64 libffi-dev amd64 3.2.1-4 [161 kB]                                  
Fetched 16.7 MB in 27s (617 kB/s)                                                                                            
Selecting previously unselected package libstdc++-5-dev:amd64.
(Reading database ... 224219 files and directories currently installed.)
Preparing to unpack .../libstdc++-5-dev_5.4.0-6ubuntu1~16.04.12_amd64.deb ...
Unpacking libstdc++-5-dev:amd64 (5.4.0-6ubuntu1~16.04.12) ...
Selecting previously unselected package g++-5.
Preparing to unpack .../g++-5_5.4.0-6ubuntu1~16.04.12_amd64.deb ...
Unpacking g++-5 (5.4.0-6ubuntu1~16.04.12) ...
Selecting previously unselected package g++.
Preparing to unpack .../g++_4%3a5.3.1-1ubuntu1_amd64.deb ...
Unpacking g++ (4:5.3.1-1ubuntu1) ...
Selecting previously unselected package build-essential.
Preparing to unpack .../build-essential_12.1ubuntu2_amd64.deb ...
Unpacking build-essential (12.1ubuntu2) ...
Selecting previously unselected package libbz2-dev:amd64.
Preparing to unpack .../libbz2-dev_1.0.6-8ubuntu0.2_amd64.deb ...
Unpacking libbz2-dev:amd64 (1.0.6-8ubuntu0.2) ...
Selecting previously unselected package libexpat1-dev:amd64.
Preparing to unpack .../libexpat1-dev_2.1.0-7ubuntu0.16.04.5_amd64.deb ...
Unpacking libexpat1-dev:amd64 (2.1.0-7ubuntu0.16.04.5) ...
Selecting previously unselected package zlib1g-dev:amd64.
Preparing to unpack .../zlib1g-dev_1%3a1.2.8.dfsg-2ubuntu4.3_amd64.deb ...
Unpacking zlib1g-dev:amd64 (1:1.2.8.dfsg-2ubuntu4.3) ...
Selecting previously unselected package libpng12-dev:amd64.
Preparing to unpack .../libpng12-dev_1.2.54-1ubuntu1.1_amd64.deb ...
Unpacking libpng12-dev:amd64 (1.2.54-1ubuntu1.1) ...
Selecting previously unselected package libfreetype6-dev:amd64.
Preparing to unpack .../libfreetype6-dev_2.6.1-0.1ubuntu2.5_amd64.deb ...
Unpacking libfreetype6-dev:amd64 (2.6.1-0.1ubuntu2.5) ...
Selecting previously unselected package libfontconfig1-dev:amd64.
Preparing to unpack .../libfontconfig1-dev_2.11.94-0ubuntu1.1_amd64.deb ...
Unpacking libfontconfig1-dev:amd64 (2.11.94-0ubuntu1.1) ...
Selecting previously unselected package libgdbm-dev.
Preparing to unpack .../libgdbm-dev_1.8.3-13.1_amd64.deb ...
Unpacking libgdbm-dev (1.8.3-13.1) ...
Selecting previously unselected package libice-dev:amd64.
Preparing to unpack .../libice-dev_2%3a1.0.9-1_amd64.deb ...
Unpacking libice-dev:amd64 (2:1.0.9-1) ...
Selecting previously unselected package libtinfo-dev:amd64.
Preparing to unpack .../libtinfo-dev_6.0+20160213-1ubuntu1_amd64.deb ...
Unpacking libtinfo-dev:amd64 (6.0+20160213-1ubuntu1) ...
Selecting previously unselected package libncursesw5-dev:amd64.
Preparing to unpack .../libncursesw5-dev_6.0+20160213-1ubuntu1_amd64.deb ...
Unpacking libncursesw5-dev:amd64 (6.0+20160213-1ubuntu1) ...
Selecting previously unselected package libsm-dev:amd64.
Preparing to unpack .../libsm-dev_2%3a1.2.2-1_amd64.deb ...
Unpacking libsm-dev:amd64 (2:1.2.2-1) ...
Selecting previously unselected package libsqlite3-dev:amd64.
Preparing to unpack .../libsqlite3-dev_3.11.0-1ubuntu1.5_amd64.deb ...
Unpacking libsqlite3-dev:amd64 (3.11.0-1ubuntu1.5) ...
Selecting previously unselected package libssl-dev:amd64.
Preparing to unpack .../libssl-dev_1.0.2g-1ubuntu4.20_amd64.deb ...
Unpacking libssl-dev:amd64 (1.0.2g-1ubuntu4.20) ...
Selecting previously unselected package x11proto-xext-dev.
Preparing to unpack .../x11proto-xext-dev_7.3.0-1_all.deb ...
Unpacking x11proto-xext-dev (7.3.0-1) ...
Selecting previously unselected package libxext-dev:amd64.
Preparing to unpack .../libxext-dev_2%3a1.3.3-1_amd64.deb ...
Unpacking libxext-dev:amd64 (2:1.3.3-1) ...
Selecting previously unselected package x11proto-render-dev.
Preparing to unpack .../x11proto-render-dev_2%3a0.11.1-2_all.deb ...
Unpacking x11proto-render-dev (2:0.11.1-2) ...
Selecting previously unselected package libxrender-dev:amd64.
Preparing to unpack .../libxrender-dev_1%3a0.9.9-0ubuntu1_amd64.deb ...
Unpacking libxrender-dev:amd64 (1:0.9.9-0ubuntu1) ...
Selecting previously unselected package libxft-dev.
Preparing to unpack .../libxft-dev_2.3.2-1_amd64.deb ...
Unpacking libxft-dev (2.3.2-1) ...
Selecting previously unselected package x11proto-scrnsaver-dev.
Preparing to unpack .../x11proto-scrnsaver-dev_1.2.2-1_all.deb ...
Unpacking x11proto-scrnsaver-dev (1.2.2-1) ...
Selecting previously unselected package libxss-dev:amd64.
Preparing to unpack .../libxss-dev_1%3a1.2.2-1_amd64.deb ...
Unpacking libxss-dev:amd64 (1:1.2.2-1) ...
Selecting previously unselected package libxt-dev:amd64.
Preparing to unpack .../libxt-dev_1%3a1.1.5-0ubuntu1_amd64.deb ...
Unpacking libxt-dev:amd64 (1:1.1.5-0ubuntu1) ...
Selecting previously unselected package tcl8.6-dev:amd64.
Preparing to unpack .../tcl8.6-dev_8.6.5+dfsg-2_amd64.deb ...
Unpacking tcl8.6-dev:amd64 (8.6.5+dfsg-2) ...
Selecting previously unselected package tcl-dev:amd64.
Preparing to unpack .../tcl-dev_8.6.0+9_amd64.deb ...
Unpacking tcl-dev:amd64 (8.6.0+9) ...
Selecting previously unselected package tk8.6-dev:amd64.
Preparing to unpack .../tk8.6-dev_8.6.5-1_amd64.deb ...
Unpacking tk8.6-dev:amd64 (8.6.5-1) ...
Selecting previously unselected package tk-dev:amd64.
Preparing to unpack .../tk-dev_8.6.0+9_amd64.deb ...
Unpacking tk-dev:amd64 (8.6.0+9) ...
Selecting previously unselected package libffi-dev:amd64.
Preparing to unpack .../libffi-dev_3.2.1-4_amd64.deb ...
Unpacking libffi-dev:amd64 (3.2.1-4) ...
Processing triggers for man-db (2.7.5-1) ...
Processing triggers for doc-base (0.10.7) ...
Processing 4 added doc-base files...
Registering documents with scrollkeeper...
Processing triggers for install-info (6.1.0.dfsg.1-5) ...
Setting up libstdc++-5-dev:amd64 (5.4.0-6ubuntu1~16.04.12) ...
Setting up g++-5 (5.4.0-6ubuntu1~16.04.12) ...
Setting up g++ (4:5.3.1-1ubuntu1) ...
update-alternatives: using /usr/bin/g++ to provide /usr/bin/c++ (c++) in auto mode
Setting up build-essential (12.1ubuntu2) ...
Setting up libbz2-dev:amd64 (1.0.6-8ubuntu0.2) ...
Setting up libexpat1-dev:amd64 (2.1.0-7ubuntu0.16.04.5) ...
Setting up zlib1g-dev:amd64 (1:1.2.8.dfsg-2ubuntu4.3) ...
Setting up libpng12-dev:amd64 (1.2.54-1ubuntu1.1) ...
Setting up libfreetype6-dev:amd64 (2.6.1-0.1ubuntu2.5) ...
Setting up libfontconfig1-dev:amd64 (2.11.94-0ubuntu1.1) ...
Setting up libgdbm-dev (1.8.3-13.1) ...
Setting up libice-dev:amd64 (2:1.0.9-1) ...
Setting up libtinfo-dev:amd64 (6.0+20160213-1ubuntu1) ...
Setting up libncursesw5-dev:amd64 (6.0+20160213-1ubuntu1) ...
Setting up libsm-dev:amd64 (2:1.2.2-1) ...
Setting up libsqlite3-dev:amd64 (3.11.0-1ubuntu1.5) ...
Setting up libssl-dev:amd64 (1.0.2g-1ubuntu4.20) ...
Setting up x11proto-xext-dev (7.3.0-1) ...
Setting up libxext-dev:amd64 (2:1.3.3-1) ...
Setting up x11proto-render-dev (2:0.11.1-2) ...
Setting up libxrender-dev:amd64 (1:0.9.9-0ubuntu1) ...
Setting up libxft-dev (2.3.2-1) ...
Setting up x11proto-scrnsaver-dev (1.2.2-1) ...
Setting up libxss-dev:amd64 (1:1.2.2-1) ...
Setting up libxt-dev:amd64 (1:1.1.5-0ubuntu1) ...
Setting up tcl8.6-dev:amd64 (8.6.5+dfsg-2) ...
Setting up tcl-dev:amd64 (8.6.0+9) ...
Setting up tk8.6-dev:amd64 (8.6.5-1) ...
Setting up tk-dev:amd64 (8.6.0+9) ...
Setting up libffi-dev:amd64 (3.2.1-4) ...


3. 將 PPA 添加到 Ubuntu 系統中 :

tony1966@tony1966-AOD255 ~ $ sudo add-apt-repository ppa:deadsnakes/ppa
[sudo] password for tony1966:
You are about to add the following PPA:
 This PPA contains more recent Python versions packaged for Ubuntu.

Disclaimer: there's no guarantee of timely updates in case of security problems or other issues. If you want to use them in a security-or-otherwise-critical environment (say, on a production server), you do so at your own risk.

Update Note
===========
Please use this repository instead of ppa:fkrull/deadsnakes.

Reporting Issues
================

Issues can be reported in the master issue tracker at:
https://github.com/deadsnakes/issues/issues

Supported Ubuntu and Python Versions
====================================

- Ubuntu 18.04 (bionic) Python2.3 - Python 2.6, Python 3.1 - Python 3.5, Python3.7 - Python3.11
- Ubuntu 20.04 (focal) Python3.5 - Python3.7, Python3.9 - Python3.11
- Ubuntu 22.04 (jammy) Python3.7 - Python3.9, Python3.11
- Note: Python2.7 (all), Python 3.6 (bionic), Python 3.8 (focal), Python 3.10 (jammy) are not provided by deadsnakes as upstream ubuntu provides those packages.

Why some packages aren't built:
- Note: for focal, older python versions require libssl<1.1 so they are not currently built
- Note: for jammy, older python versions requre libssl<3 so they are not currently built
- If you need these, reach out to asottile to set up a private ppa

The packages may also work on other versions of Ubuntu or Debian, but that is not tested or supported.

Packages
========

The packages provided here are loosely based on the debian upstream packages with some modifications to make them more usable as non-default pythons and on ubuntu.  As such, the packages follow debian's patterns and often do not include a full python distribution with just `apt install python#.#`.  Here is a list of packages that may be useful along with the default install:

- `python#.#-dev`: includes development headers for building C extensions
- `python#.#-venv`: provides the standard library `venv` module
- `python#.#-distutils`: provides the standard library `distutils` module
- `python#.#-lib2to3`: provides the `2to3-#.#` utility as well as the standard library `lib2to3` module
- `python#.#-gdbm`: provides the standard library `dbm.gnu` module
- `python#.#-tk`: provides the standard library `tkinter` module

Third-Party Python Modules
==========================

Python modules in the official Ubuntu repositories are packaged to work with the Python interpreters from the official repositories. Accordingly, they generally won't work with the Python interpreters from this PPA. As an exception, pure-Python modules for Python 3 will work, but any compiled extension modules won't.

To install 3rd-party Python modules, you should use the common Python packaging tools.  For an introduction into the Python packaging ecosystem and its tools, refer to the Python Packaging User Guide:
https://packaging.python.org/installing/

Sources
=======
The package sources are available at:
https://github.com/deadsnakes/

Nightly Builds
==============

For nightly builds, see ppa:deadsnakes/nightly https://launchpad.net/~deadsnakes/+archive/ubuntu/nightly
 More info: https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa
Press Enter to continue or Ctrl+C to cancel

Executing: /tmp/tmp.1DA53clwH1/gpg.1.sh --keyserver
hkp://keyserver.ubuntu.com:80
--recv-keys
6A755776
gpg: requesting key 6A755776 from hkp server keyserver.ubuntu.com
gpg: key 6A755776: public key "Launchpad PPA for deadsnakes" imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)

這台的 Linux Mint 是 v18, 所以看來可以安裝 Python3.11. 


4. 用 apt install 指令安裝新版 Python 3 :

安裝 Python3.11 居然說找不到此套件 : 

tony1966@tony1966-AOD255 ~ $ sudo apt install python3.11  
Reading package lists... Done
Building dependency tree       
Reading state information... Done
E: Unable to locate package python3.11 
E: Couldn't find any package by glob 'python3.11'
E: Couldn't find any package by regex 'python3.11'

我又重新更新套件清單 : 

tony1966@tony1966-AOD255 ~ $ sudo apt update   
Get:2 http://ppa.launchpad.net/deadsnakes/ppa/ubuntu xenial InRelease [18.1 kB]                                              
Ign:3 http://packages.linuxmint.com serena InRelease                                                                         
Hit:4 http://archive.ubuntu.com/ubuntu xenial InRelease                                                                      
Get:5 http://archive.ubuntu.com/ubuntu xenial-updates InRelease [99.8 kB]                                                    
Get:6 http://archive.ubuntu.com/ubuntu xenial-backports InRelease [97.4 kB]                                                  
Get:7 http://security.ubuntu.com/ubuntu xenial-security InRelease [99.8 kB]                                                  
Hit:8 http://archive.canonical.com/ubuntu xenial InRelease                                                                   
Hit:9 http://packages.linuxmint.com serena Release                                                                           
Hit:1 https://deb.opera.com/opera stable InRelease                                                                           
Fetched 315 kB in 10s (29.5 kB/s)                                                                                            
Reading package lists... Done
Building dependency tree       
Reading state information... Done
4 packages can be upgraded. Run 'apt list --upgradable' to see them.

再次安裝 python3.11 仍然找不到套件 : 

tony1966@tony1966-AOD255 ~ $ sudo apt install python3.11  
Reading package lists... Done
Building dependency tree        
Reading state information... Done
E: Unable to locate package python3.11
E: Couldn't find any package by glob 'python3.11'
E: Couldn't find any package by regex 'python3.11'

退而求其次改安裝 python3.10 還是找不到 : 

tony1966@tony1966-AOD255 ~ $ sudo apt install python3.10  
Reading package lists... Done
Building dependency tree       
Reading state information... Done
E: Unable to locate package python3.10
E: Couldn't find any package by glob 'python3.10'
E: Couldn't find any package by regex 'python3.10'

再次降到 python3.9 有找到且順利安裝 : 

tony1966@tony1966-AOD255 ~ $ sudo apt install python3.9  
Reading package lists... Done
Building dependency tree        
Reading state information... Done
Note, selecting 'postgresql-plpython3-9.5' for regex 'python3.9'
The following additional packages will be installed:
  libpq5 postgresql-9.5 postgresql-client-9.5 postgresql-client-common postgresql-common
Suggested packages:
  locales-all postgresql-doc-9.5
Recommended packages:
  postgresql-contrib-9.5 sysstat
The following NEW packages will be installed:
  libpq5 postgresql-9.5 postgresql-client-9.5 postgresql-client-common postgresql-common postgresql-plpython3-9.5
0 upgraded, 6 newly installed, 0 to remove and 4 not upgraded.
Need to get 4199 kB of archives.
After this operation, 16.7 MB of additional disk space will be used.
Do you want to continue? [Y/n] y   
Get:1 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 libpq5 amd64 9.5.25-0ubuntu0.16.04.1 [79.2 kB]
Get:2 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 postgresql-client-common all 173ubuntu0.3 [28.4 kB]
Get:3 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 postgresql-client-9.5 amd64 9.5.25-0ubuntu0.16.04.1 [878 kB]
Get:4 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 postgresql-common all 173ubuntu0.3 [154 kB]                 
Get:5 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 postgresql-9.5 amd64 9.5.25-0ubuntu0.16.04.1 [3018 kB]      
Get:6 http://archive.ubuntu.com/ubuntu xenial-updates/universe amd64 postgresql-plpython3-9.5 amd64 9.5.25-0ubuntu0.16.04.1 [40.6 kB]
Fetched 4199 kB in 7s (567 kB/s)                                                                                             
Preconfiguring packages ...
Selecting previously unselected package libpq5:amd64.
(Reading database ... 226626 files and directories currently installed.)
Preparing to unpack .../libpq5_9.5.25-0ubuntu0.16.04.1_amd64.deb ...
Unpacking libpq5:amd64 (9.5.25-0ubuntu0.16.04.1) ...
Selecting previously unselected package postgresql-client-common.
Preparing to unpack .../postgresql-client-common_173ubuntu0.3_all.deb ...
Unpacking postgresql-client-common (173ubuntu0.3) ...
Selecting previously unselected package postgresql-client-9.5.
Preparing to unpack .../postgresql-client-9.5_9.5.25-0ubuntu0.16.04.1_amd64.deb ...
Unpacking postgresql-client-9.5 (9.5.25-0ubuntu0.16.04.1) ...
Selecting previously unselected package postgresql-common.
Preparing to unpack .../postgresql-common_173ubuntu0.3_all.deb ...
Adding 'diversion of /usr/bin/pg_config to /usr/bin/pg_config.libpq-dev by postgresql-common'
Unpacking postgresql-common (173ubuntu0.3) ...
Selecting previously unselected package postgresql-9.5.
Preparing to unpack .../postgresql-9.5_9.5.25-0ubuntu0.16.04.1_amd64.deb ...
Unpacking postgresql-9.5 (9.5.25-0ubuntu0.16.04.1) ...
Selecting previously unselected package postgresql-plpython3-9.5.
Preparing to unpack .../postgresql-plpython3-9.5_9.5.25-0ubuntu0.16.04.1_amd64.deb ...
Unpacking postgresql-plpython3-9.5 (9.5.25-0ubuntu0.16.04.1) ...
Processing triggers for libc-bin (2.23-0ubuntu11.3) ...
Processing triggers for man-db (2.7.5-1) ...
Processing triggers for ureadahead (0.100.0-19.1) ...
ureadahead will be reprofiled on next reboot
Processing triggers for systemd (229-4ubuntu21.31) ...
Setting up libpq5:amd64 (9.5.25-0ubuntu0.16.04.1) ...
Setting up postgresql-client-common (173ubuntu0.3) ...
Setting up postgresql-client-9.5 (9.5.25-0ubuntu0.16.04.1) ...
update-alternatives: using /usr/share/postgresql/9.5/man/man1/psql.1.gz to provide /usr/share/man/man1/psql.1.gz (psql.1.gz) in auto mode
Setting up postgresql-common (173ubuntu0.3) ...
supported-versions: WARNING! Unknown distribution: linuxmint
ubuntu found in ID_LIKE, treating as Ubuntu
supported-versions: WARNING: Unknown Ubuntu release: 18.1
Adding user postgres to group ssl-cert

Creating config file /etc/postgresql-common/createcluster.conf with new version

Creating config file /etc/logrotate.d/postgresql-common with new version
Building PostgreSQL dictionaries from installed myspell/hunspell packages...
  en_us
Removing obsolete dictionary files:
Setting up postgresql-9.5 (9.5.25-0ubuntu0.16.04.1) ...
Creating new cluster 9.5/main ...
  config /etc/postgresql/9.5/main
  data   /var/lib/postgresql/9.5/main
  locale en_US.UTF-8
  socket /var/run/postgresql
  port   5432
update-alternatives: using /usr/share/postgresql/9.5/man/man1/postmaster.1.gz to provide /usr/share/man/man1/postmaster.1.gz (postmaster.1.gz) in auto mode
Setting up postgresql-plpython3-9.5 (9.5.25-0ubuntu0.16.04.1) ...
Processing triggers for libc-bin (2.23-0ubuntu11.3) ...
Processing triggers for ureadahead (0.100.0-19.1) ...
Processing triggers for systemd (229-4ubuntu21.31) ...

但是安裝完畢輸入 python3.9 卻找不到此指令 : 

tony1966@tony1966-AOD255 ~ $ python3.9  
No command 'python3.9' found, did you mean:
 Command 'python3.5' from package 'python3.5-minimal' (main)
python3.9: command not found

用 ls 檢視 /usr/bin 底下的所有安裝的 Python 居然找不到 3.9 版 : 

tony1966@tony1966-AOD255 ~ $ ls -ls /usr/bin/python* 
   0 lrwxrwxrwx 1 root root       9 Nov 24  2017 /usr/bin/python -> python2.7
   0 lrwxrwxrwx 1 root root       9 Nov 24  2017 /usr/bin/python2 -> python2.7
3412 -rwxr-xr-x 1 root root 3492624 Mar  2  2021 /usr/bin/python2.7
   0 lrwxrwxrwx 1 root root       9 Jun  6  2017 /usr/bin/python3 -> python3.5
4352 -rwxr-xr-x 2 root root 4456208 Jan 27  2021 /usr/bin/python3.5
4352 -rwxr-xr-x 2 root root 4456208 Jan 27  2021 /usr/bin/python3.5m
   0 lrwxrwxrwx 1 root root      10 Jun  6  2017 /usr/bin/python3m -> python3.5m

重新開機還是沒有, 我的 Linux 知識太淺薄, 不知問題出在哪裡, 明天有空再研究. 參考 : 



2023-04-20 補充 : 

仔細看上面的安裝過程才發現原來安裝的並非 Python3.9, 而是 Postgre 與 Python 相關的套件. 基本上除非這台的 Linux Mint 升版, 否則應該無法升到 3.8 版以上了. 

Linux 更新套件清單出現 "public key is not available" 錯誤的解決辦法

昨天整理辦公室櫃子找到以前二哥上大瀚機器人時使用的 Acer D255 小筆電 (CPU 是 Atom N450, 乃 amd64 單核), 因為內建的 Win7 已無法使用, 後來 (約 2017 年時) 硬碟被我格式化改安裝了 Linux Mint, 但隨即束之高閣. 它的電池已壞但插電還能開機使用. 

今天想說在上面安裝 Thonny, 還可以用來跑跑 Python 程式, 我的原則就是要物盡其用, 但是我用 apt update 指令更新套件清單時卻出現 "public key is not available: NO_PUBKEY DD3C368A8DE1B7A0" 錯誤 :  
 
tony1966@tony1966-AOD255 ~ $ sudo apt update 
[sudo] password for tony1966:
Ign:2 http://packages.linuxmint.com serena InRelease                                                                        
Hit:3 http://archive.ubuntu.com/ubuntu xenial InRelease                                                                     
Hit:4 http://security.ubuntu.com/ubuntu xenial-security InRelease                                                           
Hit:5 http://archive.canonical.com/ubuntu xenial InRelease                                                                  
Hit:6 http://archive.ubuntu.com/ubuntu xenial-updates InRelease                                                             
Hit:7 http://packages.linuxmint.com serena Release                     
Get:1 https://deb.opera.com/opera stable InRelease [2590 B]            
Err:1 https://deb.opera.com/opera stable InRelease                                 
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY DD3C368A8DE1B7A0    
Hit:9 http://archive.ubuntu.com/ubuntu xenial-backports InRelease
Fetched 2590 B in 7s (367 B/s)
Reading package lists... Done
Building dependency tree      
Reading state information... Done
782 packages can be upgraded. Run 'apt list --upgradable' to see them.
W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: https://deb.opera.com/opera stable InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY DD3C368A8DE1B7A0
W: Failed to fetch http://deb.opera.com/opera/dists/stable/InRelease  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY DD3C368A8DE1B7A0
W: Some index files failed to download. They have been ignored, or old ones used instead.
 
爬文在下面這篇找到解決辦法 :


原來只要用 sudo apt-key adv 指令在後面附上 public key 即可. 不過它提供的第一個 key 伺服器 keys.gnupg.net 已掛點無法下載 :

tony1966@tony1966-AOD255 ~ $ sudo apt-key adv --keyserver keys.gnupg.net --recv-keys DD3C368A8DE1B7A0    
Executing: /tmp/tmp.T3Sc4HuoUR/gpg.1.sh --keyserver
keys.gnupg.net
--recv-keys
DD3C368A8DE1B7A0
gpg: requesting key 8DE1B7A0 from hkp server keys.gnupg.net
?: keys.gnupg.net: Host not found
gpgkeys: HTTP fetch error 7: couldn't connect: Success
gpg: no valid OpenPGP data found.
gpg: Total number processed: 0
gpg: keyserver communications error: keyserver unreachable
gpg: keyserver communications error: public key not found
gpg: keyserver receive failed: public key not found

改用另一個 key 伺服器 keyserver.ubuntu.com 就可以順利安裝 key 了 :

tony1966@tony1966-AOD255 ~ $ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys DD3C368A8DE1B7A0   
Executing: /tmp/tmp.MxsGmug9Bz/gpg.1.sh --keyserver
keyserver.ubuntu.com
--recv-keys
DD3C368A8DE1B7A0
gpg: requesting key 8DE1B7A0 from hkp server keyserver.ubuntu.com
gpg: key 8DE1B7A0: public key "Opera Software Archive Automatic Signing Key 2021 <packager@opera.com>" imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)

解決 public key 問題再次執行 sudo apt update 就能順利更新清單了 : 

tony1966@tony1966-AOD255 ~ $ sudo apt update    
[sudo] password for tony1966:
Ign:2 http://packages.linuxmint.com serena InRelease                                                                        
Hit:3 http://archive.canonical.com/ubuntu xenial InRelease                                                                  
Hit:4 http://packages.linuxmint.com serena Release                                                                          
Get:1 https://deb.opera.com/opera stable InRelease [2590 B]                                   
Get:6 https://deb.opera.com/opera stable/non-free amd64 Packages [1184 B]     
Get:7 http://security.ubuntu.com/ubuntu xenial-security InRelease [99.8 kB]                                                 
Hit:8 http://archive.ubuntu.com/ubuntu xenial InRelease  
Get:9 http://archive.ubuntu.com/ubuntu xenial-updates InRelease [99.8 kB]          
Get:10 http://archive.ubuntu.com/ubuntu xenial-backports InRelease [97.4 kB]                   
Get:11 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 Packages [2049 kB]
Get:12 http://archive.ubuntu.com/ubuntu xenial-updates/main i386 Packages [1525 kB]                                         
Fetched 3875 kB in 35s (111 kB/s)                                                                                           
Reading package lists... Done
Building dependency tree      
Reading state information... Done
782 packages can be upgraded. Run 'apt list --upgradable' to see them.

最後用 sudo apt upgrade 更新套件 :

tony1966@tony1966-AOD255 ~ $ sudo apt upgrade   

因為太久沒更新了, 累積達 700 多項, 這花了三個多小時, 在約 72% 時停住出現一個選項 : 




我查到下面這篇, 它建議按 Y 安裝套件維護者的更新版本 :


選好後大約過 10 幾分鐘就完成更新了. 

2023年4月17日 星期一

Python 學習筆記 : 用 itertools.permutations() 排列字集

以前高師大英語所碩班的同學明中昨晚來電詢問 : 如果有 1500 個字的英文字集每次挑 12 個字出來排列會有多少種不同的排列? 電腦的算力能否處理? 關於第一個問題, Python 的內建模組 math 內有一個 perm() 函式可輕易計算出來 (> v3.8) : 

Python 3.11.2 (C:\Users\User\AppData\Local\Programs\Python\Python311\python.exe)
>>> import math   
>>> math.perm(1500, 12)     
124147257394529035596269620244764800000
>>> print("%e" %math.perm(1500, 12))       # 用科學表示法呈現
1.241473e+38

哇, 是 38 次方等級的龐然大物, 不知 PC 能否扛得起哩. 不過還會加上一些限制條件, 或許不會到這麼龐大啦 (其實還是很大), 參考 :


此處摘要一下數學中排列 (permutation) 與組合 (combination) 的差別, 排列與順序有關, 組合則與順序無關, 元素一樣但順序不一樣算不同的排列, 但卻是同一種組合, 例如 a, b, c 三個字元每次挑兩個, 有 ab, ba, ac, ca, bc, cb 六種排列, 但卻只有 ab, ac, bc 三種組合 (因為 ab/ba, ac/ca, bc/cb 都各算一種組合), 其數學公式如下 : 



雖然可以用 math.factorial() 函式根據上面的算式來計算排列組合數, 但在 Python 3.8 版後 math 模組新增了 perm()comb() 函式, 可用來分別計算排列數與組合數, 不需要自行套公式來算, 參考 :


組合數因為與順序無關會比排列數來得少, 1500 取 12 結果是 29 次方等級 :

>>> math.comb(1500, 12)   
259179212333589356687471649875   
>>> print("%e" %math.comb(1500, 12))    
2.591792e+29

在 1500 個字集準備好之前, 我先用 A~Z 這 26 個字母做個簡單測試, 作法是利用 Python 標準函式庫 itertools 中的 permutations() 函式來列出所有排列, 參考 : 


itertools.permutations() 函式可傳入兩個參數 : 


第一個參數為可迭代物件 (必要參數), 第二個參數 (備選參數) 是傳回值的排列長度 (即選幾個來排列), 例如從 26 個英文字母中取 5 個來排列 : 

>>> import math  
>>> from itertools import permutations     
>>> letters=list('ABCDEFGHIJKLMNOPQRSTUVWXYZ')     
>>> letters   
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
>>> math.perm(26, 5)      # 26 取 5 有近 79 萬種排列方式
7893600
>>> for p in permutations(letters, 5): 
    print(p)                          # 會印很久
    
將近 79 萬種排列在互動環境就跑了好久啊! 真不敢想像那 38 次方會怎樣! 不過, 在互動環境 print 結果本來就慢很多, 我將上面的指令加上計時功能寫成如下程式檔案, 並將排列結果輸出到檔案, 在 Thonny 中執行就快多了, 也才用了 30 秒不到 : 

# perm_test.py
import time
import math
from itertools import permutations

start=time.time()
letters=list('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
f=open('permutation.csv', 'w')
for p in permutations(letters, 5):
    f.write(','.join(p) + '\n')
f.close()
end=time.time()
print(f'time elapsed : {end-start}')

>>> %Run perm_test.py
time elapsed : 27.593969345092773   

結果得到一個大小約 84MB 的 csv 檔, 節錄內容頭尾如下 :


.......


雖然看來很快, 但還無法估算 38 次方要跑多久才跑得完, 以及檔案有多大. 


2023-04-20 補充 :

昨天收到測試用的 238 字字集, 存在 A~Z 欄的 Excel 檔案裡, 我將其另存成 CSV 檔 : 




其中連續的逗號來自空格, 清除換列字元與空格後, 實際字數為 238 字. 如果從 238 個字中挑選 12 個, 其排列數計算如下 :

>>> import math   
>>> math.perm(238, 12)    
24917297304498261278500684800
>>> print("%e" %math.perm(238, 12))    
2.491730e+28

哇, 是 18 次方等級的. 

接著寫了如下之程式來處理 (238, 12) 的排列情況 :

# words_permutation.py
import time
import math
from itertools import permutations

start=time.time()
with open('TW_seed_phrase_test.csv', 'r', encoding='utf8') as f:
    lines=f.readlines()
words_str=','.join(lines)
words_str=words_str.replace('\n', '')
words_list=words_str.split(',')
words_list=list(filter(lambda word: word != '', words_list))
words_list.sort()
with open('words_permutation.csv', 'w', encoding='utf8') as f:
    for p in permutations(words_list, 12):
        f.write(' '.join(p) + '\n')
print(words_list)
print(len(words_list))
end=time.time()
print(f'time elapsed : {end-start}')

此處先用字串的 split() 方法以逗號為界將字串 words_str 拆成串列, 但 EXCEL 中的空格會在匯出為 CSV 檔時產生連續逗號, 拆解時會在串列中變成空字串, 這裡利用了內建函式 filter() 來清除這些空字串, 它的傳入參數是一個傳回 True/Fasle 的函式 (辨認可迭代物件之元素是否為空字串), filter() 會將傳回 True 的可迭代物件元素傳回, 參考 : 


然後將請裡過的 words_list 串列丟給 math.permutations() 去做排列, 它會傳回一個 generator, 只要迭代此 generator 就可以產生各個排列結果 (tuple), 將此 tuple 以空格隔開組成字串後寫入輸出檔案即可. 關於檔案讀寫參考 :


跑了 5 個多小時還沒結束 ...... 持續觀察中. 

跑了快 6 小時發現程式因為 "maximum recursion depth exceeded" (超過最大迭代深度) 跳離, 同時 400 多 GB 的硬碟也快用光了 : 

Python 3.11.2 (C:\Users\User\AppData\Local\Programs\Python\Python311\python.exe)
>>> object address  : 00000229B953BDC0
object refcount : 2
object type     : 00007FF838D13550
object type name: RecursionError 
object repr     : RecursionError('maximum recursion depth exceeded')
lost sys.stderr

Process ended with exit code 1.

檢視輸出檔真的來到 424GB 左右 : 




用 EXCEL 開啟時會詢問 CSV 的區隔字元, 可看出輸出結果正確, 只是檔案太大開了好久都沒開起來只好放棄 : 




看樣子必須想辦法切割輸出的 CSV 檔了.