2024年9月25日 星期三

MicroPython 學習筆記 : 非 ASCII 字元自動轉成 Unicode 問題

這幾天在修改 xtools 模組以便能在 v1.23 版韌體中能正常發送 Line 訊息時, 發現在 MicroPython 中中文字元一律會被轉成 \u 開頭的 Unicode 字元, 例如 : 

MicroPython v1.23.0 on 2024-06-02; Generic ESP32 module with ESP32
Type "help()" for more information.
>>> v1=100   
>>> v2='您好'    
>>> params={'v1': v1, 'v2': v2}   
>>> ['{}={}'.format(k, v) for k, v in params.items()]    
['v1=100', 'v2=\u60a8\u597d']    

但是我在 PC 的標準 Python 上測試卻不會被轉成 Unicode, 而是顯示原來的中文 :

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.
>>> v1=100   
>>> v2='您好'    
>>> params={'v1': v1, 'v2': v2}   
>>> ['{}={}'.format(k, v) for k, v in params.items()] 
['v1=100', 'v2=您好']      

好奇怪, 詢問 ChatGPT 才知道這其實是 Python 執行環境版本的問題, 不同的 Python 的內建字串顯示函式 repr() 會考量裝置的資源限制 (主要是記憶體) 而有不同的實作 : MicroPython 是在資源有限的嵌入式裝置上運行, 它會將非 ASCII 字元自動轉換為 Unicode 以保字串的輸出能一致; 但在標準 Python 上則因為有豐富的 Unicode 顯示支援會直接顯示這些非 ASCII 字元而無須轉成 Unicode. 總之, 在 MicroPython 和標準 CPython 的 repr() 函數的行為差異與它們的設計目標和資源限制有關。

以下摘錄自 ChatGPT 回覆 : 

問 : 為何標準的 CPython 的 repr() 不轉成 unicode, 而 MicroPython 的卻自動轉換?  

1. MicroPython 的設計考量

  • 資源受限的環境:MicroPython 專為資源有限的嵌入式系統(如 ESP32、ESP8266)設計,內存、存儲等資源相對較少。因此,MicroPython 對字串處理的實現更加簡化。
  • repr() 的簡化處理:在 MicroPython 中,repr() 的行為被簡化,非 ASCII 字符會自動被轉換為 Unicode 轉義序列(\uXXXX),以便在資源受限的環境中正確處理和顯示非 ASCII 字符。這樣做的好處是確保在不同的終端環境中,即使終端不支援中文或其他特殊字符,也能看到唯一標識符來代表這些字符。
  • 一致性與兼容性:通過將所有非 ASCII 字符轉換為 Unicode 編碼,MicroPython 保證在嵌入式系統中的輸出行為更加一致。這樣的設計可以避免一些特殊字符在不同終端或顯示器上產生不預期的行為。

2. CPython 的設計考量

  • 桌面和服務器環境:標準 CPython 針對的是桌面、服務器等更高資源的環境。這些環境中,內存、存儲、顯示器等資源通常不會像嵌入式系統那樣受限,因此 CPython 可以直接顯示 Unicode 字符而不需要轉義。
  • repr() 的行為:在 CPython 中,repr() 的主要目的是提供一個開發者可以識別並重現的物件表示,但它不會自動將所有非 ASCII 字符轉換為 Unicode 編碼。當字串中包含可打印的非 ASCII 字符(如中文),CPython 的 repr() 會直接顯示這些字符,而不是將它們轉換為轉義序列。
  • Python 3 的 Unicode 支持:Python 3 本身對 Unicode 有更好的支持,所有字串都是 Unicode 字符串。CPython 的環境資源豐富,因此可以直接顯示包含非 ASCII 字符的字串,並且這樣做在大多數情況下更符合開發者的期望。

差異總結:

  • MicroPython:由於內存和處理能力受限,對於字串的表示會更保守,因此會將非 ASCII 字符自動轉換為 Unicode 轉義序列。這樣可以保證嵌入式系統上字串的輸出更加一致,並且避免潛在的顯示或處理問題。
  • CPython:資源充裕,並且對於字串處理有強大的 Unicode 支持。因此,當使用 repr() 時,如果字串包含可顯示的非 ASCII 字符(如中文),它會直接顯示這些字符,而不進行轉義。
原來如此, 真是長知識了. 

沒有留言:

張貼留言