2024年5月17日 星期五

SVG : path 加不加 Z 差很多

2024年5月17日 星期五

為了解決筆順練習的工具可以在 iOS 中一次下載多個部件或筆畫,認真的研究了一下 SVG 圖形的語法,哈!新手上路,總是有些地方混沌不清(根本亂玩)。不過,遇到問題總是件好事,由一個點出發,挖出了不少盲點與有用的資訊。

筆順練習的筆順資料,基上會使用到的就是 SVG 中的幾個 path 的指令:

  • M : MoveTo
  • L : LineTo
  • Q : QuadTo
  • C : CubicTo

原本以為找出對應關係,就這樣簡單,頂多是加上,部件是由多個筆畫的 path 組合起來這個程序,就能完成一個 SVG 檔案中,放入多個部件的 path,使用者,要運用時,再將部件利用軟體中的「拆解」或「分解」功能來拆開就好。而前兩天在 iOS 中使用 Keynote、Pages 或是 Numbers 也是確實如此。不過,來看看 [圖1] ,當我將我的筆順練習工具製作好的 SVG 檔,插入到 LibreOffice Impress 中時,卻有不同的結果:

[圖1] LibreOffice Impress

「雄」這個字的第一個部件,第一筆畫和第二筆畫交叉處,[圖1] 藍色箭頭和綠色箭頭是不是長得不一樣?

在 SVG 的 path 指令中有一個「Z」可以用來標示 path 結束了,[圖1] 左側的字就是沒有加上「Z」的結果,而右側的字,在每一個筆畫的指令字串最後面加上「Z」以,就正常顯示了。

這讓我想起,在使用 HTML5 的 canvas 繪圖指令時,有沒有加上 closePath 也是有差的,當初好像也卡了好久才發覺。

關於 SVG path 還可以使用哪些指令,可以參考 Mozilla 的這個線上說明:

目前筆順練習工具可以在「部件拆解」的頁面中,下載全字的部件或是筆畫 SVG 格式圖片

[圖2] 筆順練習下載 SVG 圖檔的選單

在 LibreOffice 或 Apple 的 Office 工具中,「部件」的話,一個字可以分解到以部件為基本單位,而「筆畫」則可以拆解到以筆畫為基本單位,依自己的需求下載不同的 SVG 圖檔。

相關文章


2024年5月15日 星期三

JavaScript : 計算中文字的字數與取Unicode

2024年5月15日 星期三

在檢查我的筆順練習工具是否有抓到教育部「國字標準字體學習網」的全部筆順資料時(根據網站說明,目前收錄 6030個國字,但清單中有 6063個),比對完,發現我少以下幾個字(括號內為 Unicode):

  • 嫏(5ACF)、广(5E7F)、桕(6855)、鯝(9BDD)、𥑮(2546E)、硓(7853)

然後這六個字的音檔都改用 .m4a 的格式了,所以分析音檔路徑的程式也得修改。

另外,在教育部國字標準字體學習網的清單檔案(PDF)中,序號1266的字(Unicode 5F5D),筆順資料庫中目前並沒有,只能找到一個跟它同音的字(Unicode 5F5E)

查了一下全字庫的資料,不細看,實在分不太出來:

兩個字的注音都是「ㄧˊ」。

在新增的六個字裡,「𥑮」的 Unicode 是「2546E」,這讓我發現自己用了十幾年的程式有個大臭蟲。

原來我在 JavaScript 中,用來計算多少個字,都是直接用 .length 來取得,例如:

var words = '這是新的字𥑮';
console.log(words.length);

照以前的經驗,應該會顯示結果為「6」;今天遇到「𥑮」就變成「7」了!

原來「𥑮」這個字是 UTF-32 的,而 JavaScript 是 UTF-16 的環境,所以 '𥑮'.length 會是「2」。這下子,我的程式遇到這些 UTF-32 的字就全亂了!

沒關係,總有解決方法的。利用 Array.from 可以將字串的字一個個地切開,並放入陣列中,我只要取陣列有幾個元素就好了,可以利用這個來測試:

var words = '這是新的字𥑮';
console.log( Array.from(words) );

它會顯似這樣的結果:

(6) ['這', '是', '新', '的', '字', '𥑮']

另一個問題是如何取得中文字的 Unicode?

以前我是使用 charCodeAt(0) 來取得 Unicode,像這樣:

'𥑮'.charCodeAt(0).toString(16).toUpperCase()

但是因為「𥑮」是 UTF-32 的,所以得改用 codePointAt(0) 才行:

'𥑮'.codePointAt(0).toString(16).toUpperCase()

哈!有時遇到新的狀況,時間要花很多,但是問題得以解決,更是開心啊!不過,程式改東改西,還得再觀察個幾天再上線的好,不然,掃了使用者的興可不好。

相關文章


2024年5月12日 星期日

Life: the world has moved on and we believe it no longer needs ...

2024年5月12日 星期日

Google 的 Closure 專案發展了十幾年了,看到這則聲明「Closure Library is in Maintenance Mode」:

聲明中有一句:

 In short, the world has moved on and we believe it no longer needs Closure Library.

「the world has moved on and we believe it no longer needs ...」這句型可以套用在很多人、事、物上,時代在進步,隨著時光的推演,沒有什麼是不可取代的;潮起、潮落,後浪推前浪本就是一件很正常的事,許多人老是糾結在哪兒,一直淘醉在過去的光環中,而無法接受現在的自己,只能說是想不開。


2024年5月11日 星期六

Google : 雲端硬碟的 MIME type

2024年5月11日 星期六

之前研究過如何由 Google 雲端硬碟公開分享的資料夾或是檔案連結中,解析出圖片及影音的直接取用網址;這幾天發現用同樣的方法,也可以解析出純文字檔案(例如: .html、.txt、.xml ......)的內容,主要是雲端硬碟判定是純文字檔的,就可以直接預覽內容,而預覽的內容會有一個擷取的網址。這有什麼好處呢?可以不用透過 CORS proxy 就能直接下載內容,不用受制於別旳網站,就是讓人覺得愉悅。

不過,就在開心有新的發現時,也發現很怪的事。像 .gpx 的檔案,內容明明就是 XML 格式的純文字檔,Google 雲端硬碟卻判定它的 MIME type 是「application/gpx+xml」,而不是「text/xml」。在雲端硬碟的檔案清單中就可以看到同樣內容的檔案,只是使用的檔案名稱不同,圖示就不一樣:

觀察一下:

  • 2024-04-30-hiking-gpx.xml 是可預覽的 text/xml 文件。
  • 2024-04-30-hiking.gpx 是無法預覽的 application/gpx+xml 文件。

試著打開檔案 2024-04-30-hiking-gpx.xml  的截圖是:

2024-04-30-hiking.gpx 的截圖是:

實驗了一下,只要在上載之前,將檔案名稱結尾改用 .xml ,上載到雲端硬碟後,它就會被判定為可預覽的純文字檔案了。不過,如果是上載到雲端硬碟以後,在雲端硬碟中改檔案名稱是無效的,可見 MIME type 是在上載時就已儲存在檔案資訊中,並不會因為線上改檔名,就將判定的結果改掉。

當然囉~如果能在不改檔案名稱,就能直接抓出文字內容,就更棒了,繼續研究看看有沒有其它的方法。


2024年5月10日 星期五

Hiking : 台北大縱走第七段

2024年5月10日 星期五

之前在政大環山道變電站旁,看過標有「土地公廟」的小徑,昨天滿足了它通到指南路哪處的好奇心,刻意去走走,上到樟山寺後,再由飛龍步道下山;特別帶了 GPS 手錶記錄軌跡,結果天弄了個大烏龍,居然沒儲存到軌跡,只有分段的時間點:

  • 政大四維堂 >> 土地公廟 : 00:15:22
  • 土地公廟 >> 樟山寺 : 00:44:42
  • 樟山寺 >> 政大後門 : 01:13:57

下山後看到大學同學約今天走台北大縱走第七段的訊息,本來考慮到指南宮竹柏參道的一千多階的階梯,我的左腳 IT Band 不知能不能負荷,想偷懶坐公車去指南宮站等著會合的;但那段很久沒去爬了,也較具特色,還是捨命陪君子了。反正真走不動了,指南宮站還有遊園小巴士可以「後送」。就這麼衝動地,差一點把第七段走完了!


幾個分段點記錄的時間點:

  • 指南宮竹柏參道登山口 >> 指南宮 : 10:25~11:08
  • 指南宮凌霄寶殿 >> 大成殿步道登山口 : 11:40~12:17
  • 茶展中心步道 >> 茶推廣中心停車場 : 12:17~13:11
  • 茶推廣中心 >> 阿義師大茶壺餐廳 : 13:11~13:25
  • 阿義師大茶壺 >>  樟樹步道口 : 14:32~14:55

在大茶壺用完餐,路過貓空纜車站的山上豆花店時,因為看到滿滿的人,本來的計畫是先去樟樹步道等同學拿完剩下的兩顆台北大縱走第七段的寶石,再回頭吃冰;結果我的左腳在樟樹步道頭的大陡坡就不聽話了。大家為了我,只好決定先回頭吃冰,寶石就以後再來拿。

今天開始走指南宮竹柏參道就綁上髕骨帶,挺過了陡上的一千多階,也挺過了大成殿步道的陡下,再加碼茶展中心步道的陡上。或許直接走指南路的柏油路,經草湳,再到貓纜站的走法,可以讓左腳的使用時間再拉長一點吧!不過,至少回家後,晚上還可以正常地由四樓走到一樓,應該算恢復的不錯了!


2024年5月2日 星期四

Hiking:新店秘境+大香山~貓空

2024年5月2日 星期四

 三月底曾經由政大後門出發,走了個順時針方向的「樟湖山+待老坑山+員潭子坑山環形路線」,最近山上桐花大開,想測試一下自己的雙腳到底能走多遠,順便看看桐花。先騎機車在「秘境」中確認一下路線及路況,上山的走法果然會迷路,一開始,就像落入迷魂陣中;哈~幸好只要摧油就好了,多繞個幾圈就記住路線了。原本就預計雙腳如果聽話,就走完三月底路線的反方向,不然,到了貓空,就有纜車,有小型公車可以搭下山。這 B 計畫果然派上場。底下是 2024/04/30 走完以後的軌跡地圖連結及截圖:

上山前先去木新市場買了飯團才由一壽橋到對景美溪對岸,進入新店上山。前面做足了功課有差,完全照預計路線到了大香山登山口。不過,這一個多小時的連續陡坡,把左腳的 IT bank 繃緊了,在大香山的公車亭休息兼吃午餐,才繼續後半段的行程。

上路前,怪怪的左腳先綁了臏骨帶,速度放慢,一步步踩,長春路底的下坡過關了,後面大部份都是上坡,就這樣路過了龍騰御櫻,到了優人神鼓劇場旁,樟湖步道的入口。2023年4月底也曾騎自行車上來過(參「雄:Biking : 春崎產業道路+樟湖步道 」),那時看到較多桐花,今天則可能因為前幾天的大雨,花都被打落,連地上的都不見。

小插曲是,為了不想爬高高的階梯,過了優人神鼓劇場以後,選擇鑽往竹林的小路,走著走著,愈看愈不像以前牽自行車走過的,而且路有往右偏的趨勢,只好找到往左偏的叉路,幸好又修正回以前有走過的路線了。

在樟湖步道和瓦厝支線的交會處及聆風亭各休息了好一會兒才由瓦厝茶坊進入指南路34巷的柏油路,此時天空烏密布,雨就不客氣地下了起來。幸好看起來已停業的「迺妙茶廬」前有遮棚,躲一會兒,雨就稍小了。

快到貓纜站「相思炭窯」對面有賣冰的,爬完山當然要來一碗剉冰。點了一碗黑糖剉冰,加了粉園、薏仁跟花生,55元一大碗,山上賣的,價錢居然沒有比平地貴,算是有良心的店家,真的要給個讚才行!

本來想搭貓纜下山的,為了怕遇到因為落雷,纜車還沒到山下就停駛,只好乖乖地等小巴士。傻傻地坐在纜車站旁的公車候車亭等小10,後來才發現應該要去商店旁的路邊等車才對,不然,等它去茶展中心再回來時,不就滿滿的客人了。幸好在那輛小10後面又來一輛棕15小巴,棕15是經由茶展中心就直接下山的,二話不說,就跳上車了。

經過這一次的測試,長陡坡5公里,我的左腳就不行了,下回應該要早一點綁上臏骨帶的。另外,伸展一定要做,回家後雖然左腳的 IT band 很有感,有空就伸展,影響就減到最小。隔了一天,今天再去政大的環山道以一個小時,走了一圈,完全正常。

相關連結


2024年4月25日 星期四

Apps Script : 多帳號登入與 PERMISSION_DENIED

2024年4月25日 星期四

 有人反應「雄:TPET-生生用平板-師師有法寶-筆順練習QRCode產生器」無法製件筆順練習的 QR code。由於之前偷懶,如果程式卡住並不會顯示錯誤訊息,所以稍微改了一下程式的流程,讓它至少出現錯誤代碼可以除錯。底下是可能的訊息:

ScriptError: 很抱歉,讀取儲存空間時發生伺服器錯誤。錯誤代碼: PERMISSION DENIED.

找了一下,全英文的可能是這樣:

ScriptError: We're sorry, a server error occurred while reading from storage. Error code PERMISSION_DENIED

不管中文,還是英文,總之就是程式的權限有問題;可是明明有授權給程式了,為什麼又出現問題?

在努力的抓錯時,突然想到之前「雄:Google Apps Script Web App 發布後網址的問題」中遇到多帳號登入 Google 時,如果操作 Google Apps Script 不是使用第一個登入的帳號,會發生一些奇奇怪的問題。

於是在 Chrome 裡開了一個「無痕式視窗」,在只有一個帳號登入 Google 的情形下,「筆順練習 QRCode產生器」就能正常使用了。

所以要解決前面說到旳「PERMISSION_DENIED」,大概有三個方向:

  • 只用一個 Google 帳號登入。
  • 使用「無痕式視窗」,但只使用一個 Google 帳號登入。
  • 已多個 Google 帳號登入了,以第一個帳號來開啟帶有程式的 Google 文件。

為了怕日後久了,自己又忘為什麼程式沒動作,也提醒使用者解決的方法,「筆順練習 QRCode產生器」如果遇到權限問題,就會跳出警示,類似這樣的畫面:

相關連結






2024年4月18日 星期四

GlobalSat GH-625B 資料傳輸腳位

2024年4月18日 星期四

前一陣子看到家裡回收區小孩丟掉的手錶,讓我想起很久以前,妹妹給我的 GlobalSat GH-625B  GPS 手錶,找了半天,才找到。將回收區撿回的粉紅色錶帶,裝在 GH-625B 上,哈!戴在我手上,實在太搶眼了,不過聊勝於無。

GH-625B 是利用一條專屬的 USB 傳輸線和電腦連接,傳輸資料,看來,這條傳輸線應該是類似我以前買的 PL2303,它們都是使用 Prolific USB to Serial  的驅動程式。靠近手錶側的端子有四個插孔,圖形的端子有一個凹槽,這防呆的設計,滿好辨識方向的。我利用電錶先找出 5V 和 GND 以後,將它接到 Arduino 上測試,也找出了 RX 和 TX 在哪裡:

確認傳輸線插孔的用途,GH-625B 側的四支接腳的用途,就能對應出來了:


拿 CP2102 USB-TTL ,按圖將 GH-625B 的 RX、TX 和 CP2102 的 TX、RX 對接,再將 5V 接 5V,GND 接 GND


先以 Python 查詢一下 CP2102 是在哪一個 port,執行:

python -m serial.tools.list_ports

再以 pykmaze 測試看看能不能抓到 GH-625B 內儲存的基本資料(假設 CP2102 在 com3):

python pykmaze.py -p com3 -i -f

在 GH-625B 上可以看到

CMD:784748

表示成功執行了查詢的指令。這樣子,以後不怕原廠附的傳輸線壞掉了。pykmaze 原來無法用 Python 3.x 來執行,順便將它改為可以適用於 Python 3.x ,改天再放到 GitHub 中。

相關連結





2024年4月17日 星期三

QuickChart 替代 Google Chart QR Code 產生器

2024年4月17日 星期三

以前需要在程式中利用一個網址產生需要的 QR Code 圖片時,總是使用 Google Chart 的 API;今天朋友提醒我 HTML5 FUN PK 無法製作 QR Code,查了一下,Google 已經不再提供這個服務了。詳見:

在 Google 的論壇中,則有人提供了替代的方法:

我選擇暫時先以 QuickChart 的 QR Code API 來代替,語法可以參考這裡:

待測的其它選擇:

有空可能還是要再來研究一下不必靠某網站,又能跨平臺「自己自足」的方式,不然真的是牽一髮而動全身,剛剛總共改了九個不同的工具和遊戲,還不知道有沒有遺漏的呢!

2024年4月2日 星期二

Python : 轉換 DataFrame 帶有逗號的數字字串為純數字

2024年4月2日 星期二

在設計「雄:Python : 匯出 PDF 表格為試算表資料」中的轉換工具,由 PDF 擷取而來的資料被轉為pandas 的 DataFrame,最後使用 DataFrame 的 to_excel 輸出為 Excel 格式的檔案。不過如果照預設值,輸出的資料在Excel中,都是「文字」的格式;此外同事提供的原始資料,除了流水號的欄位,其它欄位的數字都有加上逗號(例: 12,345、7,890),所以在將「文字格式」的數字轉為數字型態時,得多考慮這一點。

在 Python 中,將文字型態的數字,轉為數字型態的方法有很多,不過,試了一下,如果想將「12,345」轉為「12345」,使用 locale 的 atof 或是 atoi 應該是較簡潔,例如:

import locale
from locale import atof

locale.setlocale(locale.LC_NUMERIC, '')
atof('12,345')

但是如果遇到不是數字的內容,或是空字串,例如:

atof('這不是數字')
atof('')

就會出現類似這樣的錯誤訊息:

ValueError: could not convert string to float: ''

所以在轉換的時候,還需要檢查一下是否為數字的。

判斷是否為數字,可以使用 Python 的 isnumeric() ,不過,像以下的格式:

  • 12,345
  • -12345
  • 12.345

因為帶有逗號、減號或小數點,isnumeric() 都會傳回 False,所以我先利用 re.sub ,將非數字的符號先拿掉後,再用 isnumeric() 來判斷。

綜合前面的條件,利用底下的 convert_number_strings_to_numbers ,就可以用來將 df (pandas 的 DataFrame) ,指定的欄位 columns (欄位順號 list),轉為 float 數字:

def convert_number_strings_to_numbers(df, columns):
  locale.setlocale(locale.LC_NUMERIC, '')
  for i in columns:
    df[i] = df[i].apply(lambda x: x if x=='' or not re.sub(r'[,.-]', '', x).isnumeric() else atof(x))
  return df

相關文章


2024年4月1日 星期一

Python : 匯出 PDF 表格為試算表資料

2024年4月1日 星期一

很多行政工作如果規畫、整合得當是可以不用花那麼多時間的;反之,沒有整合,就是整死人。記得以前看學校幹事們忙著在電腦上剪剪貼貼資料,忙得人仰馬翻的,總覺得,為什麼運用電腦了,還需要這樣子「愚公移山」;關係夠好,看不下去了,就會幫忙弄些小工具,來處理資料。前幾天同事問我有沒有辦法將別人 PDF 檔中的表格資料匯出到試算表,並且將列變成行、直變橫?PDF 中的表格長這樣子:

第一個想法,Python 應該可以!幾個程序能做到,轉檔應該就有望了:

  • 以 Python 讀取 PDF 的資料,並解析出表格文字內容。
  • 去掉不要的資料。
  • 將表格內容進行旋轉(transpose)。

由讀 PDF 讀入表格資料

讓 Python 讀入 PDF 資料,並解析出表格文字內容,我試了:

  • tabula-py
  • Camelot (camelot-py)

測試過,感覺 Camelot 比較可以跟後續的資料旋轉接軌,就專心研究 camelot-py 了。

關於 camelot-py 的安裝

在 Windows 上使用 camelot-py 大概會遇到這個錯誤訊息:

OSError: Ghostscript is not installed. You can install it using the instructions here: https://camelot-py.readthedocs.io/en/master/user/install-deps.html

主要是因為讀入 PDF 檔案時,如果沒有指定「backend」參數,它預設會使用預設值「backend="ghostscript"」,而大部份的電腦中可能沒安裝ghostscript,有興趣可以參考錯誤訊息中的說明文件:

因為 ghostscript 的安裝顯得較複雜,所以我選擇在 Windows 中用「backend="poppler"」,只要先執行以下兩行指令安裝 pdftopng 跟 opencv 即可:

pip install pdftopng
pip install opencv-python

倒過來,如果在 Google Colab 的環境中,安裝 pdftopng 反而會累死人(我是沒成功),安裝 ghostscript 容易多了:

!apt install python3-tk ghostscript
!pip install  ghostscript

關於 camelot-py 的使用

假設 pdf_file_name 是 PDF 的路徑,pages 中放了要讀入資料的頁碼 list,只要這樣就可以讀取資料:

import camelot
pdfTable = camelot.read_pdf(pdf_file_name, pages=pages)

如果不是用 ghostscript,就用:

import camelot
pdfTable = camelot.read_pdf(pdf_file_name, pages=pages, backend="poppler")

接下來我們就可以針對 pdfTable 來存取(轉換)資料,詳情可以參考 camelot-py 中,有關 Table 的說明:

我使用 pdfTable[0].df ,將抓到資料轉為 pandas.DataFrame 的格式,方便後續的資料處理。

資料處理

前面提到利用 pdfTable[0].df ,可以將指定頁資料轉為 pandas.DataFrame 物件,假設將內容指定給變數 df,我想針對 df 再進行一些處理:

  • 只取出指定的列(之後會旋轉為欄)。
  • 去掉原始資料最右側的「小計」那欄。
  • 暫存原始資料最左側欄的資料(最後為試算表中的欄位名稱)。
  • 去掉流水號不是數字(空格或是「以下空白」)的資料。
  • 將一頁頁資料合併在一起

pandas 的 DataFrame,在存取資料時,幾個關鍵詞跟對象有關:

  • index
  • colunms
  • axis

幾個關鍵詞跟過濾、移動指標有關:

  • isin
  • iloc
  • loc

資料的刪除、旋轉、合併的關鍵詞:

  • drop
  • transpose
  • concat

詳細的說明都可以在pandas的網站查到:

為了寫這個資料轉換的工具,第一次玩  Camelot 和 pandas,雖然還沒有很深入研究,但工具有了初步的成果了,將它移植到 Google Colab 中,想玩玩看(哈!不能提供有個資的 PDF 啦!) ,或是對原始碼有興趣(別嫌我,醜是一定的,就好玩,亂寫的),網址如下:

pdf-to-excel.ipynb 的截圖

改天再補記一下曾經卡關很久的地方。

相關文章


2024年3月25日 星期一

Hiking : 樟湖山+待老坑山+員潭子坑山環形路線

2024年3月25日 星期一

 看天氣好,原本只是想再爬爬樟山寺,看看會不會又像之前,下山時 ITBS 又犯,順便再玩一下很久沒用,放到沒電的 GPS 手錶。結果走得太開心,在樟山寺稍休息後,一路接上了樟湖步道瓦厝支線,由優人神鼓經龍騰御櫻,到新店大香山,再下切到一壽橋,走河堤回到恆光橋,連成一個環形路線。

在河堤上拍了這張全景,剛好可以將今天爬過的幾個山頭都入鏡,由左側稍低的政大,走飛龍步道,上到樟山寺所在的樟湖山;接到樟湖步道的待老坑山;最後到照片右側新店的員潭子坑山。

今天的軌跡匯入到 Google Maps,如下:

看了一下 GPS 手錶的記錄,總里程 11.31km,總時間 03:10:08 (需要再扣掉在河堤上和已大一的學生聊天的半小時)。

2024-03-25 10:52:21 出發

2024-03-25 11:12:30 飛龍步道登山口

2024-03-25 11:26:26 樟山寺展望

2024-03-25 11:44:53 樟湖步道瓦厝支線入口

2024-03-25 11:54:05 瓦厝附近


2024-03-25 11:57:39 樟湖步道主線叉路

2024-03-25 12:03:30 優人神鼓

2024-03-25 12:08:52 龍騰御櫻

2024-03-25 12:14:08 往員潭子坑山的路口

2024-03-25 12:25:54 大香山公車站

2024-03-25 13:12:57 一壽穚

2024-03-25 13:23:25 河堤上全景


其實這路線的點,除了往樟山寺的飛龍步道以外,其它都騎過自行車,不過,這一次是全程用走的,IT band 是有一點緊,但幸好沒開始痛,看來的確是需要稍加訓練一下,並做伸展,這樣它就會乖乖的。

2024年3月18日 星期一

Python: googletrans 與 bilingual_book_maker

2024年3月18日 星期一

2023年3月應朋友的要求,將開源的專案「bilingual_book_maker」可以在 Colab 中使用(參見:雄:OpenAI : ChatGPT 應用 : 製作雙語電子書),利用它可以把 EPUB 格式的電子書變成「雙語」的內容。前一陣子陸續有人反應有問題,不過,因為我根本沒在使用,加上有時問題會在一陣子後又消息了,所以沒有積極地去查原因。前天換有在使用的朋友跟我說了,哈!開始認真地找解方。

底下記錄一下排除問題的關鍵。

httpx 版本的問題

googletrans 已經滿久沒更新了,而 openai 持續地在更新,但是兩者都有用到 httpx,一個要舊版的,一個要新版的,因此安裝完 googletrans 以後,出現了「dependency conflicts」的錯誤訊息:

  Building wheel for googletrans (setup.py) ... done
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
openai 1.14.1 requires httpx<1,>=0.23.0, but you have httpx 0.13.3 which is incompatible.

httpx 版本的衝突,由訊息看來,因為 googletrans 是後安裝的,所以最後 httpx 用的版本是 0.13.3 ,而不是 openai 要的版本( >=0.23.0 )。這也導致開始翻譯時,出現了這些訊息:

Traceback (most recent call last):
  File "/usr/local/bin/bbook_maker", line 5, in <module>
    from book_maker.cli import main
  File "/usr/local/lib/python3.10/dist-packages/book_maker/cli.py", line 7, in <module>
    from book_maker.translator import MODEL_DICT
  File "/usr/local/lib/python3.10/dist-packages/book_maker/translator/__init__.py", line 2, in <module>
    from book_maker.translator.chatgptapi_translator import ChatGPTAPI
  File "/usr/local/lib/python3.10/dist-packages/book_maker/translator/chatgptapi_translator.py", line 7, in <module>
    from openai import AzureOpenAI, OpenAI, RateLimitError
  File "/usr/local/lib/python3.10/dist-packages/openai/__init__.py", line 8, in <module>
    from . import types
  File "/usr/local/lib/python3.10/dist-packages/openai/types/__init__.py", line 5, in <module>
    from .image import Image as Image
  File "/usr/local/lib/python3.10/dist-packages/openai/types/image.py", line 5, in <module>
    from .._models import BaseModel
  File "/usr/local/lib/python3.10/dist-packages/openai/_models.py", line 23, in <module>
    from ._types import (
  File "/usr/local/lib/python3.10/dist-packages/openai/_types.py", line 23, in <module>
    from httpx import URL, Proxy, Timeout, Response, BaseTransport, AsyncBaseTransport
ImportError: cannot import name 'BaseTransport' from 'httpx' (/usr/local/lib/python3.10/dist-packages/httpx/__init__.py)

openai 比較重要,試著以它為主,讓 googletrans 使用較新版本的 httpx 看看,也就是安裝 googletrans 時,不要檢查 dependency,將原本的安裝指令:

!pip -q install  googletrans==4.0.0-rc1

多加「--no-dependencies」改為:

!pip -q install --no-dependencies googletrans==4.0.0-rc1

httpcore 的問題

前面雖然解決了 googletrans 安裝時的問題,執行時,換 httpcore 有問題,出現了這樣的錯誤訊息:

AttributeError: module 'httpcore' has no attribute 'SyncHTTPTransport'

查了一下,可以在使用 googletrans 前,先執行:

import httpcore
setattr(httpcore, 'SyncHTTPTransport', 'AsyncHTTPProxy')

利用這兩行來 patch,只要比 googletrans 先執行,就不會出現 AtributeError。

httpx[http2]

本以為可以順利執行 google 翻譯了吧!結果又出現這樣的訊息:

Using http2=True, but the 'h2' package is not installed. Make sure to install httpx using `pip
install httpx[http2]`.

不過,這看起來比較好解決,就照提示,安裝 httpx[https] 就好,所以在安裝 googletrans 之前,先執行:

!pip -q install httpx[http2]

經過以上的修正,終於可以讓 googletrans 順利地和 bilingual_book_maker 搭配,以 google 翻譯來進行翻譯。

不過,為了讓使用更有彈性來選擇是否以 googletrans 幫 bilingual_book_maker 執行 google 翻譯的功能,我加上了「install_googletrans」的設定參數,如果勾選了,就使用 googletrans ,否則使用 bilingual_book_maker 專案內建的功能。這樣子,必要的時候,可以選擇關閉我亂改的部份,直接執行 bilingual_book_maker,也方便除錯。

這個雖然是自己沒在使用的工具,累積了除錯及解決問題的能力,時間沒有白花,收穫還挺多的,相信它是一個善的循環。

相關文章


2024年3月3日 星期日

3DP : Delta 校正尺寸大小

2024年3月3日 星期日

第二部 3D printer 是 Delta 型的,當初滑塊、效應器都是自己用 PLA 印的,PLA 的缺點就是久了會脆化,所以都忘記已經重印過幾次了。年前在檢修、測試時,效應器又部份零件斷了,加上熱敏電阻 NTC 也斷了,索性一次下單,通通換成金屬件。

這幾次很認真的調校,重新復習靭體的各參數,忘了什麼時候改用 Marlin 1.1.9.1 的,暫時不換版本。Marlin 有支援 M665 可以讓我們先以 G-code 來邊改邊測試,調校時,可以用:

M665 H289.9

H289.9 將 Z 的最大高度設為 289.9 mm。

可以用:

M665 L217

L217 將懸臂的長度設為 217mm。

這部機器三軸及調度調校完以後,列印完 20x20x20 的測試方塊後, Z 的調度沒問題,但是 X / Y 的尺寸卻是略小,只有 19.84mm:


Marlin 中,跟 X / Y 尺寸大小相關的參數是 DELTA_DIAGONAL_ROD,我目前 Configuration.h 中的的設定是:

#define DELTA_DIAGONAL_ROD 217

要將 217 調整為多少呢?應該是 20mm 的大小,卻印出 19.84mm ,所以依比例計算一下:

217 * 19.84 / 217 = 215.264

可以先用 G-code 來暫時改一下 DELTA_DIAGONAL_ROD,下這樣的指令:

M665 L215.264

重新再印一次 20x20x20 的方塊,確定尺寸正確了,再修改 Marlin 的參數:

#define DELTA_DIAGONAL_ROD 215.264


久沒摸了,不少東西忘了,不過,稍加複習一下,好像又喚醒了沉睡的能力。比較頭痛的是線材吸了不少水份,還沒進到料管就斷了,要來試試看有什麼方法救。


2024年2月29日 星期四

Biking : 春崎產業道路

2024年2月29日 星期四

天氣狀況 : 陰

TRIP DIST : 7.03
TRIP TIME : 0:33:52
AVG. SPEED : 12.4
MAX. SPEED : 42.4

今年居然在櫻花開得最茂盛時,忘了騰龍御櫻。雖然花不多了,還是要補一下功課,騎一趟春崎產業道路。不過,看來今天我的體力不行,自行車的碼錶也不給力,只記錄到一半的行程。

在東山高中上來的叉路口喝水,遠遠就看得到騰龍御櫻的櫻花。兩位女士正在路口猶豫要如何回到汽車停放的杏花林。她們由樟湖步道走下來的,要再由老泉街45巷走上杏花林,有一點距離,幸好下午太陽不見了,不然一定曬到哀哀叫。

氣喘噓噓地過了春崎的第一個大彎道,不到菜園前的第二個大彎就累到下車「高尚」一下了。幸好走一小段後,又能繼續踩踏,菜園後的第三個大彎,節奏對了,踩起來就輕鬆許多。

過了菜園沒多遠的這個路口:

電線桿補一張特寫:

好奇心驅使下,就將車牽向小路去了。看到了櫻花,也看到了小木屋,那是以前去騰龍御櫻賞花時,走到最低處可見的小木屋。原來石階小路走三小段就進到騰龍御櫻了。



哈!這樣子少騎一個陡陡的大彎,直接就闖進櫻花林了。

在坡頂遇到一位年輕人騎 Gogoro 上來賞花,小聊了一下。他在家當奶爸,照顧一歲多的小孩,下午小孩的阿嬤幫忙照顧半天,他則「不勤快」地接單跑外送;只能說,選擇在家當奶爸,勇氣可嘉。

 
雄::gsyan © 2009. Design by Pocket