Claude Code 中文亂碼?Windows 3 步修好
先講重點
短答給趕時間的人:Windows 終端機預設用 CP950(繁中舊編碼),跟現代程式預設的 UTF-8 對不上,所以中文變 ??? 、方塊字、或 Python 直接吐 UnicodeEncodeError — 不是 AI 寫錯,是環境編碼。3 步修:(1) 終端機打 chcp 65001 切 UTF-8 (2) Python 程式設 PYTHONIOENCODING=utf-8 (3) 檔案存對格式 — .ps1 要 UTF-8 with BOM、.env 絕對不要 BOM。
這是我的 Threads 自動發文 bot 撞過最玄的坑:程式邏輯全對、在 Claude Code 裡跑也正常,排程半夜自動跑就跳 UnicodeEncodeError。查了很久才發現 — 同一支程式,誰來執行、用什麼編碼環境執行,結果不一樣。這篇把 Windows 中文編碼的三層問題一次講清楚,讓你少走我那幾個晚上。
為什麼會亂碼?(30 秒懂原理,修起來才不會亂槍打鳥)
文字在電腦裡是數字,「編碼」就是數字跟字的對照表。全世界現在通用的表叫 UTF-8;但 Windows 繁中版的終端機,預設還在用 1990 年代的舊表 CP950。兩邊用不同的表講話,中文就變成 ??? 或方塊 — 像兩個人拿不同版本的密碼本對暗號。
所以亂碼有三個可能的案發現場,要分開查:(1) 終端機顯示層 — 程式輸出 UTF-8、終端機用 CP950 讀 (2) Python 執行層 — 程式要輸出中文、但執行環境的輸出編碼是 CP950,直接報 UnicodeEncodeError: cp950 (3) 檔案儲存層 — 檔案本身存錯格式,打開就是亂的。下面三步一層一層解決。
第 1 步:終端機切 UTF-8(顯示層)
終端機看到亂碼,先打這行把當前視窗切到 UTF-8:
chcp 65001
65001 就是 UTF-8 的代碼頁編號。這行只對當前視窗有效,重開就恢復 CP950。想一勞永逸:Windows 11 可以在「設定 → 時間與語言 → 語言與地區 → Windows顯示語言 → 變更系統地區設定」勾選 Beta: 使用 Unicode UTF-8 提供全球語言支援 — 勾完重開機,全系統預設 UTF-8。(注意:少數老舊軟體可能因此顯示異常,遇到再取消勾選就好。)
第 2 步:Python 設輸出編碼(執行層,排程炸掉 9 成是這個)
AI 寫的 Python 程式印中文報 UnicodeEncodeError: cp950 — 尤其是「在 Claude Code 裡跑正常、丟去 Windows 排程就炸」— 因為排程執行的環境沒繼承你終端機的編碼設定。最穩的解法是設環境變數,告訴 Python 一律用 UTF-8 輸出:
# 當次生效(終端機):
set PYTHONIOENCODING=utf-8
# 永久生效(PowerShell,設定使用者層級環境變數):
[Environment]::SetEnvironmentVariable('PYTHONIOENCODING', 'utf-8', 'User')
設完永久版要重開終端機(或重新登入)才生效。這一步就是我 Threads bot 那幾個晚上的答案:程式沒錯,錯在排程器執行時的環境是乾淨的 CP950,跟我平常開著 UTF-8 終端機測試的環境不同 — 「在我電腦上可以跑」的 Windows 中文版。
判斷口訣:手動跑正常、自動跑就炸 → 查環境變數;連手動跑都炸 → 先做第 1 步再做這步。
第 3 步:檔案存對格式(儲存層,兩條鐵律)
最後一層是檔案本身。UTF-8 有一個小變體叫「UTF-8 with BOM」— 檔案開頭多 3 個隱形位元組當記號。麻煩在:Windows 有些東西一定要這記號,有些東西碰到就爆掉。背兩條鐵律就好:
- .ps1(PowerShell 指令碼)含中文 → 一定要 UTF-8 with BOM。沒有 BOM,PowerShell 5.1 會用 CP950 讀它,中文註解全成亂碼、字串比對莫名失敗,還可能報一堆看起來像語法錯誤的 UnexpectedToken — 但你的語法其實是對的。
- .env(環境變數設定檔)→ 絕對不要 BOM。很多程式讀 .env 是逐字元解析,開頭那 3 個隱形位元組會讓第一行的變數名稱多出看不見的字元,程式讀到的是「(BOM)API_KEY」而不是「API_KEY」— 值永遠讀不到,而且錯誤訊息完全看不出原因。
叫 AI 動手時直接把規則講給它:「這個 .ps1 存 UTF-8 with BOM」「.env 存 UTF-8 不要 BOM」— Claude Code 聽得懂,一次做對比事後 debug 快得多。用記事本另存新檔時,編碼下拉選單裡的「UTF-8」是無 BOM、「具有 BOM 的 UTF-8」才有,別選反。
Windows 中文亂碼三層排查:(1) 顯示層 — 終端機預設 CP950,打 chcp 65001 切 UTF-8,想永久就開系統的 Beta UTF-8 選項 (2) 執行層 — Python 報 UnicodeEncodeError: cp950,設 PYTHONIOENCODING=utf-8 環境變數,「手動跑正常、排程跑就炸」9 成是這個 (3) 儲存層 — 兩條鐵律:.ps1 含中文要 UTF-8 with BOM、.env 絕對不要 BOM。原理一句話:Windows 的舊編碼表跟現代程式的 UTF-8 對不上。這是我 Threads bot 實際踩過的坑,程式邏輯全對、環境編碼不對,一樣炸。
名詞解釋
- 編碼(encoding)
- 電腦儲存文字的方式。Windows 中文環境常用 Big5,多數程式假設 UTF-8,兩邊對不上就變亂碼 — 所以資料夾、檔案建議用英文命名。
- 終端機(terminal)
- 「用文字指令操作電腦的視窗」的統稱。Mac 叫 Terminal,Windows 上就是 PowerShell,兩者角色相同。
- PowerShell
- Windows 內建的指令視窗:用打字下指令的方式操作電腦,Claude Code 在 Windows 上就在這裡面跑。按 Win + X 可以叫出來。
- 環境變數(environment variable)
- 放在系統層、不寫進程式碼的設定值,最常用來放 API 金鑰等機密,避免跟著程式碼被公開。
- Python
- 入門門檻最低的主流程式語言之一,資料處理、自動化、AI 領域的首選。
- 排程(cron)
- 讓程式「每天 8 點」「每小時」自動執行的定時器。自動發文、定期抓資料都靠它。
- 機器人(bot)
- 自動執行特定任務的程式,例如 LINE bot 自動回訊息、發文 bot 每天定時發貼文。
相關文章
▸ 常見問題
Claude Code 輸出中文變成 ??? 或亂碼怎麼辦?
先打 chcp 65001 把終端機切到 UTF-8(Windows 繁中終端機預設用 1990 年代的 CP950 舊編碼,跟現代程式的 UTF-8 對不上)。這行只對當前視窗有效;要永久生效,去系統設定開「Beta: 使用 Unicode UTF-8 提供全球語言支援」再重開機。不是 AI 寫錯程式,是環境編碼問題,重下 prompt 沒有用。
Python 報 UnicodeEncodeError: cp950 怎麼修?
設環境變數 PYTHONIOENCODING=utf-8,強制 Python 一律用 UTF-8 輸出。當次測試用 set PYTHONIOENCODING=utf-8;永久生效用 PowerShell 打 [Environment]::SetEnvironmentVariable('PYTHONIOENCODING','utf-8','User') 然後重開終端機。特別是「手動跑正常、排程自動跑就炸」的情況 — 排程環境不繼承你終端機的編碼設定,一定要用環境變數治。
為什麼程式在 Claude Code 裡跑正常,排程執行就出現編碼錯誤?
因為執行環境不同:你的終端機可能已經切了 UTF-8,但 Windows 排程器啟動程式時用的是乾淨的預設環境(CP950、沒有你設過的當次變數)。解法是把編碼設定寫進「使用者層級環境變數」(PYTHONIOENCODING=utf-8),讓任何環境執行都吃得到。這是我的 Threads 自動發文 bot 實際踩過的坑,查了好幾個晚上。
UTF-8 跟 UTF-8 with BOM 差在哪?哪些檔案該用哪個?
BOM 是檔案開頭 3 個隱形位元組的記號。兩條鐵律:.ps1(PowerShell 指令碼)含中文一定要「with BOM」,否則 PowerShell 用舊編碼讀,會亂碼甚至報假的語法錯誤;.env(環境變數檔)絕對不要 BOM,否則第一個變數名稱會多出隱形字元、值永遠讀不到。記事本另存時「UTF-8」= 無 BOM、「具有 BOM 的 UTF-8」= 有,別選反。
看完這篇之前先確認:
- Claude Code 或它跑的程式輸出中文變 ??? 或亂碼
- AI 寫的 Python 一碰中文就 UnicodeEncodeError
- 檔案存完再開變亂碼 或 .ps1 指令碼跑不動
- Mac / Linux 用戶 (UTF-8 是預設,很少踩這雷)
- 亂碼出現在網頁上 (那是 HTML charset 問題,不是終端機)
- 還沒裝 Claude Code (先看安裝那篇)
- 以為是 AI 的問題重下 prompt — 其實是 Windows 編碼,重問一百次也一樣
- 只改了終端機沒改 Python 的輸出編碼 — 兩層要分開治
- 把 .env 存成 UTF-8 with BOM — 很多程式讀 .env 會炸