The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

如何讓 Python 程式正確的處理 UTF-8 字元編碼

最近在嘗試微軟最近推出的 MarkItDown 工具,它使用 Python 開發,可用於將各種文件檔案轉換為 Markdown 格式,支援的文件格式也非常多,這在 AI 盛行的時代是非常有用的。因為文件換為 Markdown 格式之後,可以讓大語言模型進行分析。不過我在 PowerShell 底下使用的時候,沒有意外的又出意外了,因為它無法正確的處理 UTF-8 字元的輸入輸出,所以只要遇到中文就掛掉,真的很煩,這種問題都不知道處理幾次了。這篇文章我打算來介紹如何讓 Python 程式正確的處理 UTF-8 字元。

illustrating the complexities of handling UTF-8 encoding in Python  The scene depicts colorful, interwoven binary code st

問題重現

首先我們來看看問題是如何重現的,我們可以使用下面的程式碼來重現問題:

markitdown coding-guideline.pdf > coding-guideline.md

錯誤訊息如下:

Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "C:\Python312\Scripts\markitdown.exe\__main__.py", line 7, in <module>
  File "C:\Python312\Lib\site-packages\markitdown\__main__.py", line 39, in main
    print(result.text_content)
UnicodeEncodeError: 'cp950' codec can't encode character '\u26ab' in position 4123: illegal multibyte sequence

解決這個問題,最簡單的方法是改用 -o filename 參數來指定輸出檔案,這樣就不會有問題了:

markitdown coding-guideline.pdf -o coding-guideline.md

但我有不得不用 Pipe (|) 的理由,所以這個問題我必須解決!✊

解決方法 1:透過 PYTHONUTF8 環境變數

解決方法也很簡單,給個環境變數就好:

  • 命令提示字元 (Command Prompt)

    set PYTHONUTF8=1
    set PYTHONIOENCODING=utf-8
    
  • PowerShell

    $env:PYTHONUTF8=1
    $env:PYTHONIOENCODING='utf-8'
    
  • Shell

    export PYTHONUTF8=1
    export PYTHONIOENCODING=utf-8
    

這樣就可以正確的處理 UTF-8 字元了,以下這段命令可以正常執行!👍

markitdown coding-guideline.pdf > coding-guideline.md

至於 PYTHONIOENCODINGPYTHONUTF8 環境變數的區別如下:

  • PYTHONUTF8

    Python 3.7 開始,引入了 PYTHONUTF8 環境變數。當您將 PYTHONUTF8 設定為 1 時,Python 會啟用 UTF-8 模式,這意味著 Python 會在多數情況下預設使用 UTF-8 編碼,包括檔案處理標準輸入輸出(STDIN, STDOUT)和管道(pipes)等。這有助於在不同的作業系統和地區設定中保持一致的編碼行為,減少因預設編碼不同而導致的問題。

  • PYTHONIOENCODING

    此環境變數用於指定 Python 在執行期間對標準輸入 (stdin)、標準輸出 (stdout) 和標準錯誤 (stderr) 的編碼方式。當您設定 PYTHONIOENCODINGutf-8 時,Python 會使用 UTF-8 編碼來處理這些標準流 (STDIN, STDOUT, STDERR),這對於需要處理多語言文字的應用程式特別有用。需要注意的是,這僅影響標準輸入輸出,對於使用 open() 函數讀寫檔案時的編碼,仍需在程式碼中明確指定 encoding 參數。

這意味著,當你使用的 Python 版本在 Python 3.7 以上時,你可以使用 PYTHONUTF8 環境變數來啟用 UTF-8 模式就好,設定 PYTHONIOENCODING 就顯得有點多餘。

使用建議如下:

  • 如果您僅需要修改標準輸入輸出和錯誤的編碼,且希望指定特定的編碼,可以使用 PYTHONIOENCODING

  • 如果您希望整個 Python 環境預設使用 UTF-8 編碼,建議使用 PYTHONUTF8,這樣可以確保在各種操作中都使用 UTF-8 編碼,減少編碼不一致的問題。

需要注意的是,目前 Python 最新版為 Python 3.13.1,而預計從 Python 3.15 開始,將預設啟用 UTF-8 模式,這意味著未來版本的 Python 將自動使用 UTF-8 作為預設編碼。這對於處理 UTF-8 字元的問題,將會是一個很大的改進!🎉

解決方法 2:透過 -X utf8 參數

第二種解決方法,則是靠 python 指令的 -X utf8 參數來指定編碼,這樣也確實可以解決問題!

python -X utf8 -m markitdown

終端機輸出顯示與非法多字元序列相關的 UnicodeEncodeError。錯誤發生在執行 Python 腳本時,並展示使用 UTF-8 編碼選項的建議修正。

相關連結

留言評論