解決Python匯出CSV或Excel檔時,中文字顯示為亂碼的問題

解決Python匯出CSV或Excel檔時,中文字顯示為亂碼的問題

目錄

    原始文章

    解決Python匯出CSV或Excel檔時,中文字顯示為亂碼的問題


    都是編碼的問題

    不管是什麼樣的程式語言,當匯出檔案的時候,編碼都是一個讓人頭痛的問題。經常發生的情況是,你匯出了一個csv檔,在你的電腦上完全可以正常顯示,但傳給同事後,他卻回覆說打開全部都是亂碼,並表達出一種「你怎麼都沒有好好檢查」的微妙情緒。

    編碼問題之所以麻煩,因為它可能牽涉到作業系統的設定、檔案格式、編碼格式等問題。就算我能夠順利匯出正確的檔案,實際上我不清楚系統的背後發生了什麼事,但也不覺得有弄懂它的必要,只要知道哪個方法可行就可以了,相信你和我一樣也不在乎。

    針對Python的編碼問題,我會分成三個部份:

    1. 檔案格式:包括csv和xlsx兩種格式。
    2. 編碼:包括utf-8、utf-8-sig、big5等。
    3. Python模組:最常見的模組是pandas,但也可以使用csv。這篇文章不會特別討論,因為pandas看起來是把csv寫在模組裡面。

    給同事的緊急自救手冊

    在正式開始之前,我們先提供一個緊急應變方法:如果你匯出的檔案是csv,而你的同事看到的是亂碥,可以請他不要雙擊開啟檔案,也不要直接把檔案拖曳至Excel中,而試著從Excel上方的「資料 > 取得資料 > 從檔案 > 從文字/CSV」;Office 2013以前的Excel則為「資料 > 取得外部資料 > 從文字檔」。

    編碼卡關經驗

    我通常匯出檔案都是用utf-8-sig,在後面會提到。本來覺得沒什麼問題,也沒想過我會寫一篇關於編碼的文章。但就在今天,我在Mac上匯出了一份地址清單,並且在雙系統的Windows中要使用郵局的3+3郵遞區號轉碼軟體,結果匯入的檔案一直顯示亂碼,在多次的測試後終於成功,也才有了這篇文章。

    郵遞區號3+3
    郵局提供的3+3郵遞區號應用系統

    使用情境決定檔案格式

    Excel檔和CSV檔的特性不同,Excel的檔案較大,讀取寫入較慢,而且欄數和列數都有上限,列數的上限為1048576,但比較容易使用,而且在我的經驗中,Excel檔比較不容易有亂碼的問題產生。

    相反,CSV檔的檔案較小,讀取寫入較快,沒有欄數與列數的限制,壞處是有些人不習慣使用CSV檔,不太知道怎麼和它相處。

    總結來說,如果你的資料量不大,而且產出的檔案需要給其他人使用,建議你匯出成xlsx就可以了。但如果你的檔案是自己要用的,像是分析的過程中匯出暫存檔,那csv當然是個比較好的選擇,而且在Python中讀取檔案的時候也可以指定編碼,彈性更高。

    選擇適合的編碼

    以下列了三種編碼,不知道哪一種適合你嗎?別懷疑,全部試一次就對了。

    UTF-8

    UTF-8是pandas預設的編碼格式,但通常用這個方式都會出現亂碼,我只是寫出來讓大家知道一下。

    path = '路徑'
    df.to_csv(path + '/file_name.csv', index=False, encoding='utf-8')
    df.to_csv(path + '/file_name.xlsx', index=False, encoding='utf-8')
    

    UTF-8-Sig

    UTF-8-Sig和UTF-8的主要差別是前者是UTF-8 with BOM (Byte Order Mark),在Win10中翻譯成「具有BOM的UTF-8」,後者沒有BOM,總之有BOM的比較好。這個方式通常都可以順順利利、平平安安的匯出檔案,這也是網路上最多人推薦的用法。

    順帶一提,utf-8-sig事實上有兩種寫法,utf-8-sig與utf_8_sig,兩者似乎有微秒的差異,兩個都可以試一下。

    path = '路徑'
    df.to_csv(path + '/file_name.csv', index=False, encoding='utf-8-sig')
    df.to_csv(path + '/file_name.xlsx', index=False, encoding='utf-8-sig')
    

    Big5

    如果utf-8-sig不幸未能完成任務,那你可以試試big5。在我上面提到的郵遞區號3+3轉換的案例中,我最後也是用big5解決,但詭異的地方在於,用big5匯出的檔案在我的Mac上反而顯示為亂碥,在郵局的軟體中卻正常顯示。沒關係,我已經不想追究原因了。

    path = '路徑'
    df.to_csv(path + '/file_name.csv', index=False, encoding='big5')
    df.to_csv(path + '/file_name.xlsx', index=False, encoding='big5')
    

    其他編碼

    如果不幸的,以上三種方法都不能達成你的目的,你可以到codecs — Codec registry and base classes中,嘗試其他可以顯示Traditional Chinese的編碼。我在這個頁面中也找到一個ANSI的編碼,這個編碼似乎可以達成我的目的,但只有在Windows上可以使用,偉大的Python看起來也沒辦法在Mac上把UTF-8轉成ANSI,總之我最後是放棄了,也勸你不要輕易嘗試這個方法。

    python_codecs
    Standard Encodings

    編碼錯誤

    匯出檔案的時候,Python可能會回傳以下編碼錯誤的訊息,像是:

    'utf-8' codec can't encode character '\\u6052' in position 19: illegal multibyte sequence

    這個錯誤的原因是某些字元沒辦法完成編碼,可以使errors參數忽略,如下:

    df.to_csv(path + '/file_name.csv', index=False, encoding='utf-8-sig', errors='ignore')

    errors這個參數可能需要更新pandas才可以使用,像我從1.0.1更新到1.2.4後,才能順利使用。



    推薦文章

    Aron

    搭載商業思維的資料科學家,工業設計系畢業,曾任職知名品牌行銷企劃。下班後寫機器學習模型,寫網站,也寫文章。興趣是把Side Project當成創業題目來玩,把人生當成遊戲破關。

    facebook telegram

    推薦書單

    人生複本
    人生複本 ⭐⭐⭐⭐⭐
    權力遊戲:馬斯克與特斯拉的世紀豪賭
    權力遊戲:馬斯克與特斯拉的世紀豪賭 ⭐⭐⭐
    財務煉金術
    財務煉金術 ⭐⭐⭐⭐⭐
    大仙術士李白 (1)
    大仙術士李白 (1) ⭐⭐⭐⭐⭐

    發佈留言

    • * 表示必填欄位
    • 您填寫的電子郵件不會被公開
    • 請確認您的電子郵件正確無誤,當您的留言收到新的回覆時,我們會寄送通知信件給您

    發佈留言必須填寫的電子郵件地址不會公開。