Python で「UnicodeDecodeError」を解消できずファイルが読めない
テキストモードでファイルを開く際の既定エンコーディングが実ファイルと違うことが原因。
open() に encoding 引数を明示するか、バイナリモードで読んで自前デコードすると解決する。
公開: 更新:
要約
Python で UnicodeDecodeError: 'utf-8' codec can't decode byte ... などが出る場合、ファイルの実エンコーディングと open() が想定するエンコーディングが食い違っている。open(path, encoding='utf-8') のように明示的に指定する、または utf-8-sig / cp932 などファイル実態に合わせれば解消する。
よくある原因
- encoding 未指定:
open(path)だけだと OS のロケールに依存する。
Windows では cp932(Shift_JIS 系)、Linux では UTF-8 であることが多い。 - BOM 付き UTF-8: Excel で保存した CSV などは BOM が先頭に付き、
utf-8で読むと最初の文字に余計なバイトが残ることがある。 - エンコーディング誤認: 古い Windows 由来の文書を utf-8 として開いてしまう。
- 破損バイト: ネットワーク越しのバイナリ混入や、途中で切れたファイルで一部のバイト列が無効。
解決策
1. encoding を明示する
ほぼ全ての UnicodeDecodeError はこれで防げる。
with open("data.txt", encoding="utf-8") as f:
text = f.read()open() の仕様(新しいタブで開く) のとおり、テキストモードで encoding を省略するとロケール既定が使われる。
2. BOM 付き UTF-8 は utf-8-sig
import csv
with open("export.csv", encoding="utf-8-sig") as f:
rows = list(csv.reader(f))utf-8-sig は読み込み時に BOM を取り除き、書き込み時には先頭に付与する。
3. Shift_JIS / cp932
Windows のメモ帳で保存した古いファイルは cp932 が安全。
with open("legacy.txt", encoding="cp932") as f:
text = f.read()shift_jis ではなく cp932 を推奨(NEC 拡張・IBM 拡張文字を含むため)。
4. errors 引数で握り潰す
ログのような壊れても致命的でないファイルなら、errors='replace' でデコードできないバイトを U+FFFD(�)に置き換えられる(? への置換はエンコード時の挙動で、デコード時は �)。
with open("noisy.log", encoding="utf-8", errors="replace") as f:
text = f.read()5. バイナリモードで読み自前デコード
判別が必要なら chardet や charset-normalizer でエンコーディングを推定して decode する。
import charset_normalizer
raw = open("unknown.txt", "rb").read()
guess = charset_normalizer.from_bytes(raw).best()
text = str(guess)実行例
実際に上記の手順を python:3.12(Debian GNU/Linux 13 trixie)環境で動かすと、cp932 で用意したファイルを encoding 未指定で開いた段階で UnicodeDecodeError: 'utf-8' codec can't decode byte 0x93 が発生し、encoding='cp932' を明示することで正常に読み出せることが確認できる。
$ python bad.py
Traceback (most recent call last):
File "/tmp/tmp.1PbIWpiSpn/bad.py", line 2, in <module>
print(f.read())
^^^^^^^^
File "<frozen codecs>", line 322, in decode
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x93 in position 0: invalid start byte
終了コード: 1$ python solve_cp932.py
日本語テキスト$ python solve_replace.py
'���{��e�L�X�g\n'$ python solve_utf8_sig.py
utf-8-sig: 'hello'
utf-8 : '\ufeffhello'— 2026-08-02 時点の出力