Pythonの文字化けが消える UTF-8既定化とは

Pythonの文字化けが消える UTF-8既定化とは

PythonでテキストやCSVを読み込もうとしたら、いきなりUnicodeDecodeErrorが出てファイルが開けなかった経験はありませんか?

この文字化けエラーは、Windowsでcp932という日本語向けの文字コードが使われているのが原因です
MacやLinuxではあまり見かけないのに、Windowsだと急に出てくる、あの厄介なやつです

この記事では、まずなぜWindowsで文字化けが起きるのかをほどいてから、今すぐできる対策を整理します
そのうえで、Python 3.15のUTF-8既定化(PEP 686)で、この悩みがどう変わる見込みなのかまで、初心者の方向けに広く浅くまとめていきます

ジャベ雄

文字化けは、原因が分かると対策もすっきり見えてきます

この記事は2026年7月時点の情報でまとめています
Python 3.15はまだ正式リリース前(beta段階)で、正式版は2026年10月1日予定です、仕様は固まっていますが細かい文言は変わる可能性があります

目次

Pythonの文字化けがWindowsで起きる理由(cp932)

結論から言うと、Windowsで文字化けが起きるのは、encodingを指定せずにファイルを開くとWindowsの既定の文字コードcp932で読もうとするからです
そのファイルがUTF-8で保存されていると、cp932では解釈できないバイトが出てきてエラーになる、という流れです

Pythonの公式ドキュメントには、テキストモードでencodingを指定しない場合、使われるエンコーディングはOSに依存すると書かれています
Pythonが内部で今のロケール(地域・言語の設定)に合わせた文字コードを取りに行くので、その結果がプラットフォームによって変わるわけです

日本語Windowsの場合、この既定の文字コードがcp932になります
だから「encodingを書かずにopenする」と、暗黙のうちにcp932で読もうとして、UTF-8のファイルで転ぶんです

MacやLinuxで文字化けが起きにくいのはなぜか

MacやLinuxのようなUnix系のシステムは、ロケールがUTF-8になっていることが多いです
だから既定の文字コードもUTF-8寄りで、UTF-8のファイルをそのまま開いても問題が起きにくいんです

「同じコードなのに、自分のWindowsだと落ちて、同僚のMacだと動く」というすれ違いは、この既定の文字コードの違いから来ています
ただ、MacやLinuxも設定次第ではUTF-8以外になることがあるので、「Unix系なら100%大丈夫」とまでは言い切れません

ジャベ雄

Windowsだけ挙動が違うのは、地域設定の名残なんです

cp932はShift_JISとは別物です

ここで1つ、混同しやすいポイントを押さえておきます
cp932とShift_JISは、似ているけれど同じではありません

cp932は、標準のShift_JISをマイクロソフトがWindows向けに拡張したものです
漢字やひらがなの部分は同じなのですが、丸数字の①のような記号は、Shift_JISとcp932で割り当てられている値が違います

だからWindowsで作られたファイルを読むときは、encoding=”shift_jis”ではなくencoding=”cp932″を指定するのが安全です
shift_jisを指定すると、記号のところで文字化けやエラーが起きることがあります

やっかいなのは、漢字やひらがなが多い文章だと、shift_jisでもそれっぽく読めてしまう場面があることです
普段は問題なく動いていて、丸数字やローマ数字が入ったデータが来たときだけ急に転ぶ、という気づきにくい落とし穴になります

Windows由来と分かっているファイルは、はじめからcp932を指定しておくのが無難です
そうしておけば、拡張された記号が混じっていても取りこぼしなく読めます

UnicodeDecodeErrorの読み方を覚える

まずは実際にエラーを再現してみます
UTF-8で保存したファイルを、encodingを指定せずに開くと、Windowsでは次のようなエラーが出ます

# UTF-8で保存された data.txt を、encodingを書かずに開く
with open("data.txt") as f:
    text = f.read()

# ↓ Windowsだと、こんなエラーが出る
# UnicodeDecodeError: 'cp932' codec can't decode byte 0xef in position 0:
# illegal multibyte sequence

長くて身構えてしまうエラーですが、読む場所は3つだけです
この3か所さえ拾えれば、原因のあたりが付けやすくなります

読む場所意味
‘cp932’ codecどの文字コードで読もうとして失敗したか(ここではcp932)
byte 0xefどのバイトでつまずいたか
position 0ファイルの何バイト目でつまずいたか(0=先頭)

この例では先頭がBOMなので、position 0の0xefはUTF-8のBOMという印の先頭バイトになっています
cp932で読もうとしたら、いきなり1バイト目で「知らないバイトだ」となって転んだ、というわけです

BOMが無いファイルでも、日本語が先頭付近にあれば同じ種類のエラーが出ます
その場合はpositionが0以外の数字になって、日本語の1文字目のバイトでつまずいた、という読み方になります

末尾のillegal multibyte sequenceは「cp932にない、ありえないバイトの並び」という意味です
ファイルが途中で切れているときはincomplete multibyte sequence(不完全なバイト列)と出ることもあります

ジャベ雄

codec名を見れば、どの文字コードで読もうとしたか一発で分かります

今すぐできる文字化け対策4つと効き方の違い

Python 3.15を待たなくても、今のバージョンで打てる対策があります
大きく4つあって、それぞれ「どこに効くか」が違うので、そこを押さえておくと迷いません

スクロールできます
対策何に効くか効かない範囲
encoding明示自分が書いたopen()のファイル読み書きライブラリの中で開いているファイル
PYTHONUTF8=1プロセス全体(ライブラリ含む)のopen既定とprint側encodingを明示した箇所は明示が優先
-X utf8起動時にUTF-8モードを有効化(効果はPYTHONUTF8=1と同じ)同上
PYTHONIOENCODING一般に標準入出力(printや入力)側のエンコーディングopen()のファイル既定には及ばないとされる

対策1 open()にencodingを明示する(一番のおすすめ)

最優先の対策は、open()にencodingを書くことです
「どの文字コードで読むか」を自分で指定してしまえば、OSの既定に左右されなくなります

# UTF-8のファイルを読む(基本形)
with open("data.txt", encoding="utf-8") as f:
    text = f.read()

# ExcelなどでできたBOM付きUTF-8のファイルは utf-8-sig で
# (先頭に見えないゴミ文字が残らない)
with open("data.csv", encoding="utf-8-sig") as f:
    text = f.read()

# Windows由来のcp932のファイルなら cp932 を指定
with open("windows.csv", encoding="cp932") as f:
    text = f.read()

Pythonの公式も、バージョン間で挙動をそろえるためにencodingを常に明示することを推奨しています
ただしこれが効くのは自分のコードのopen()だけで、使っているライブラリが内部で開くファイルまでは面倒を見きれません

対策2 PYTHONUTF8=1 でUTF-8モードにする

環境変数PYTHONUTF8=1を設定すると、UTF-8モードが有効になります
このモードでは、open()の既定がUTF-8になり、標準入出力もUTF-8寄りになります

コマンドプロンプトでその場だけ有効にするなら、次のように打ってからPythonを動かします

set PYTHONUTF8=1
python your_script.py

いつも有効にしておきたいなら、Windowsのシステム環境変数にPYTHONUTF8を追加して値を1にしておく手もあります
この方法はencoding明示と違って、ライブラリが内部で開くファイルにも効くのが強みです

対策3 python -X utf8 で起動時に有効化する

環境変数をいじらず、その起動だけUTF-8モードにしたいときは、起動オプション-X utf8が使えます

python -X utf8 your_script.py

効果はPYTHONUTF8=1と同じで、UTF-8モードをオンにします
「この実行のときだけ試したい」という場面で手軽です

対策4 PYTHONIOENCODING はprint側の対策

環境変数PYTHONIOENCODINGは、標準入出力の文字コードを指定するものです
コンソールへのprintで文字化けする(UnicodeEncodeErrorが出る)ときの対処として、一般によく使われます

PYTHONIOENCODINGはprint側(標準入出力)向けで、open()のファイル既定には及ばないとされています
ファイルの文字化けはencoding明示かPYTHONUTF8、コンソールのprintはPYTHONIOENCODING、と役割を分けて考えると混乱しません

ジャベ雄

迷ったら、まずopen()にencodingを書くところから始めれば大丈夫です

pandasやcsvでファイルを読むときの文字化け対策

ここまではopen()の話でしたが、実務ではpandasのread_csvや標準ライブラリのcsvでファイルを読む場面も多いと思います
この2つも文字化けの考え方は同じで、要は「どの文字コードで読むか」をこちらから指定してあげればいいだけです

pandas.read_csv は encoding 引数で指定する

pandasでCSVを読むときも、encodingを渡せば文字化けを防げます
渡し方はopen()とほぼ同じで、ファイルの中身に合わせてUTF-8かcp932を選びます

import pandas as pd

# UTF-8のCSVを読む(基本形)
df = pd.read_csv("data.csv", encoding="utf-8")

# Excelで「CSV UTF-8」保存したBOM付きは utf-8-sig で
df = pd.read_csv("excel_utf8.csv", encoding="utf-8-sig")

# Excelで「CSV(コンマ区切り)」保存したcp932は cp932 で
df = pd.read_csv("excel_export.csv", encoding="cp932")

読み方の見分け方はopen()のときと同じで、Excel由来のCSVはcp932かutf-8-sigのどちらかだと思っておけば、たいていのケースはカバーできます
どちらか分からないときは、両方を試してエラーにならない方を選ぶのが手っ取り早いです

標準の csv モジュールは open() の encoding に従う

標準ライブラリのcsvモジュールは、少し立ち位置が違います
csv自身に文字コードの指定はなく、先にopen()で開いたファイルを渡す形なので、文字コードはそのopen()のencodingで決まります

import csv

# 文字コードは open() 側の encoding で決まる
# csv.reader 自体に encoding 引数は無い
with open("data.csv", encoding="utf-8", newline="") as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

つまりcsvモジュールの文字化けは、結局open()にencodingを書けば防げます
ちなみにcsvを開くときは、改行の扱いを揃えるためにnewline=””も一緒に付けるのが公式の推奨です

pandasはread_csvのencoding引数、標準csvはopen()のencoding、と入り口は違いますが、指定する文字コードの考え方は共通です
UTF-8のファイルはutf-8(BOM付きはutf-8-sig)、Windows/Excel由来はcp932、という基準はそのまま使えます

EncodingWarningでencoding未指定のopenを洗い出す

「encodingを明示するのが良いのは分かったけど、自分のコードのどこが抜けているか分からない」というときに便利な機能があります
それがEncodingWarningという警告です

この警告はPython 3.10で導入されました
encodingを指定せずにopen()している箇所を見つけて、「ここ、既定の文字コードで開いてますよ」と教えてくれます

ただし、デフォルトでは出ない設定になっているので、自分でオンにする必要があります
起動オプション-X warn_default_encoding(または環境変数PYTHONWARNDEFAULTENCODING)を付けて実行します

python -X warn_default_encoding your_script.py

これを付けて動かすと、encodingを書き忘れているopen()のところで警告が出ます
Python 3.15への引っ越し前に、直しておくべき箇所を先に洗い出せる点検ツールとして使えます

警告を出して1つずつencodingを足す手順

実際の使い方はシンプルで、警告を出して、出た場所にencodingを足す、これを繰り返すだけです
まずは点検したいスクリプトを、次のように警告オプション付きで動かしてみます

python -X warn_default_encoding your_script.py

encodingを書き忘れているopen()があると、その行を指して次のような警告が出ます
警告なので処理は止まらず、そのまま最後まで動きつつ、あやしい箇所だけ教えてくれます

your_script.py:5: EncodingWarning: 'encoding' argument not specified
  with open("data.txt") as f:

あとは警告が出た行を開いて、encodingを1つずつ足していきます
UTF-8のファイルならencoding=”utf-8″、Windows由来ならencoding=”cp932″という具合に、そのファイルに合う文字コードを書き足します

# 修正前(警告が出る)
with open("data.txt") as f:
    text = f.read()

# 修正後(encodingを足す)
with open("data.txt", encoding="utf-8") as f:
    text = f.read()

もう一度-X warn_default_encoding付きで動かして、警告がゼロになれば点検完了です
この作業をひととおり済ませておけば、Python 3.15で既定が変わっても、あわてる箇所がほぼ無くなります

ちなみに、あえてOSの既定の文字コードで開きたい箇所があるなら、encoding=”locale”と書けます
こう書いておくと「意図してロケール依存にしている」と伝わって、警告も出なくなります

📚 Python自動化の独学に効く本PR
退屈なことはPythonにやらせよう 第3版

退屈なことはPythonにやらせよう 第3版

Al Sweigart

Pythonクローリング&スクレイピング 増補改訂版

Pythonクローリング&スクレイピング 増補改訂版

加藤耕太

シゴトがはかどる Python自動処理の教科書

シゴトがはかどる Python自動処理の教科書

クジラ飛行机

私のおすすめからランダムで3冊を表示しています

Python 3.15のUTF-8既定化(PEP 686)で何が変わるのか

ここからが本題です
Python 3.15ではPEP 686という提案が採用され、既定の文字コードがOSの環境に関係なくUTF-8になる見込みです

What’s New(新機能のまとめ)にも「Pythonはシステムの環境に関係なくUTF-8を既定のエンコーディングとして使う」と書かれています
これが実現すると、Windowsでもopen(“data.txt”)のようにencodingを書かずに開いたとき、UTF-8で読んでくれるようになります

正体はUTF-8モードを既定でオンにすること

1つ大事な点があります
PEP 686は「既定のエンコーディングだけをUTF-8に差し替える」ものではなく、先ほどのUTF-8モードそのものを、既定でオンにするという内容です

だから変わるのはopen()の既定だけではありません
UTF-8モードは標準入出力にも及ぶので、print側の文字化けも減る方向になります(ただしコンソール側の設定にも左右されるので環境次第です)

読者の方向けにざっくり言うと「open()の既定がUTF-8になって、printまわりも改善する」と捉えておけば十分です
PEP 686はもともとmethaneさん(Inada Naokiさん)が2022年に提案したもので、長く予告されてきた変更でもあります

2026年10月に正式リリース予定(今はまだbeta)

気をつけたいのは、Python 3.15はまだ正式リリースされていないという点です
2026年7月時点ではbeta段階で、正式版(3.15.0)は2026年10月1日予定です

ただ、機能追加を締め切るfeature freezeは2026年5月に済んでいます
だから「UTF-8既定化を入れる」という方針そのものは、ほぼ確定と考えて良い状態です

実はドキュメントには、まだ更新が追いついていない部分があります
What’s Newは「UTF-8が既定」と書いている一方で、open()のリファレンスは今も「ロケール依存」のままです、これは修正が進行中で、3.15がまだ動いている最中という証拠でもあります

ジャベ雄

「もう文字化けが消えた」ではなく「これから消える見込み」という段階です

逆に注意 Excel由来のcp932 csvには encoding=”cp932″ が必要になる

ここで、うっかりすると新しく踏む罠があります
UTF-8にすれば全部解決、というわけではないんです

3.15より前は「UTF-8のファイルをcp932で読もうとして失敗」という文字化けでした
ところが3.15以降は、逆にcp932のファイルをUTF-8で読もうとして失敗する、というエラーが起こりえます

典型例が、Excelから「CSV(コンマ区切り)」で保存したファイルです
日本語Windowsでこの形式で保存すると、中身はcp932になることがあります、それをencoding未指定で開くと、3.15はUTF-8で読もうとして転ぶ可能性があります

対策は、これまでどおりencoding=”cp932″を明示することです

# Excelで「CSV(コンマ区切り)」保存したcp932のファイルを読む
# 3.15以降は encoding を書かないと、UTF-8で読もうとして失敗しうる
with open("excel_export.csv", encoding="cp932") as f:
    text = f.read()

ExcelのCSV UTF-8とCSVの違いを見分ける

Excelから保存したCSVの文字コードは、保存形式で変わります
保存ダイアログの「ファイルの種類」で、次のどちらを選んだかを見るのが分かりやすいです

保存形式だいたいの文字コードPythonでの読み方の目安
CSV UTF-8(コンマ区切り)UTF-8(多くはBOM付き)encoding=”utf-8-sig”
CSV(コンマ区切り)日本語Windowsではcp932になりやすいencoding=”cp932″

「CSV UTF-8」はExcel 2016以降にある比較的新しい選択肢です
ここはExcelのバージョンや環境で細かく変わる部分なので、うまくいかなければ両方の指定を試してみるのが手っ取り早いです

実務では、どちらの形式で保存されたか分からないファイルを受け取る場面も多いと思います
そんなときは、エラーが出ても止まらずに読める書き方にしておくと、原因の切り分けが楽になります

# 文字コードが分からないCSVを、順番に試して読む
for enc in ("utf-8-sig", "cp932", "utf-8"):
    try:
        with open("mystery.csv", encoding=enc) as f:
            text = f.read()
        print(f"{enc} で読めました")
        break
    except UnicodeDecodeError:
        continue

この書き方は、あくまで受け取ったファイルの文字コードが分からないときの応急処置です
自分が保存する側なら、最初からutf-8で書き出すようにそろえておくと、読むときの迷いがなくなります

ExcelとPythonをつなぐ話は、Python本体もpipも要らずにExcelの中でPythonを動かせるxlwings Lite入門でも触れています
ExcelのデータをPythonで扱いたい方は、あわせて読んでみてください

従来の挙動に戻したいとき(PYTHONUTF8=0)

cp932前提で書かれた既存のコードを動かしていて、3.15の変更で挙動が変わって困る場面もあると思います
そんなときは、従来のロケール依存の挙動に戻すこともできます

環境変数PYTHONUTF8=0、または起動オプション-X utf8=0で、UTF-8モードを無効にできます

set PYTHONUTF8=0
python your_script.py

python -X utf8=0 your_script.py

3.15の既定切り替えは、主にWindowsのユーザーでこれまでと挙動が変わる箇所が出ます
encodingを書かずにShift_JIS系のファイルを読み書きしていたコードは、エラーで止まるだけでなく、エラーも出ずに中身が壊れるケースもありえます

エラーで止まってくれるならまだ気づけますが、静かにデータが壊れるのが一番こわいパターンです
だからPYTHONUTF8=0での先送りは応急処置と考えて、原則はencodingを明示する方向で直していくのがおすすめです

3.15移行に向けて今からやっておくこと

ここまでの話を、移行前の準備という形でまとめておきます
Python 3.15はまだ先ですが、下の4つを今のうちにやっておくと、既定が変わっても慌てずに済みます

  • 自分のコードのopen()にencodingを足す(UTF-8なら”utf-8″、BOM付きは”utf-8-sig”)
  • -X warn_default_encodingで点検して、書き忘れをEncodingWarningで洗い出す
  • Excel由来の「CSV(コンマ区切り)」ファイルはencoding=”cp932″を明示しておく
  • すぐに直しきれず心配なら、しばらくPYTHONUTF8=0で従来挙動のまま様子を見る

ポイントは、先送り(PYTHONUTF8=0)はあくまで一時しのぎにして、本命はencodingの明示に寄せていくことです
encodingさえ書いてあれば、3.15になっても3.14のままでも、同じように動いてくれます

ジャベ雄

今のうちにencodingを足しておけば、移行のときにやることはほぼ無くなります

まとめ 結局どうすればいいか

ここまでを整理すると、文字化けとの付き合い方はシンプルです
Python 3.15を待つかどうかに関わらず、open()に毎回encodingを明示するのが、いちばん確実で長持ちする対策です

  • UTF-8のファイルはencoding=”utf-8″、BOM付きならutf-8-sig
  • Windows由来(Excelの「CSV」保存など)はencoding=”cp932″(shift_jisではなく)
  • ライブラリ内部まで含めて効かせたいならPYTHONUTF8=1-X utf8
  • 書き忘れの点検には-X warn_default_encodingでEncodingWarning

Python 3.15でUTF-8が既定になると、多くの人にとって文字化けはぐっと減る見込みです
ただし逆にcp932のファイルで新しい罠も生まれるので、「UTF-8にすれば全部解決」ではないという両面を覚えておくと安全です

どちらの方向の文字化けも、結局は「どの文字コードで読むかを自分で指定しておく」ことで防げます
これからPythonを入れる方は、Pythonのインストール方法もあわせて確認してみてください

エラーが読めないときはClaudeに貼って聞くのもアリ

UnicodeDecodeErrorが出たとき、エラーメッセージをそのままClaudeに貼って聞くのも手です
次のような依頼テンプレートを使うと、原因の切り分けと直し方を一緒に考えてもらえます

PythonでファイルをopenしたらUnicodeDecodeErrorが出ました
・OS: Windows
・エラー全文:(ここにエラーをそのまま貼る)
・開こうとしているファイル:(txt / csv / どこで作ったか など)

原因の見当と、encodingの指定をどう直せばいいか教えてください
コードを書き換える場合は、変更内容を先に私に提示してから進めてください

最後の一文を入れておくと、勝手にファイルを書き換えられずに済みます
提案を確認してから自分で反映すれば、気軽に相談できます

📚 Python自動化の独学に効く本PR
退屈なことはPythonにやらせよう 第3版

退屈なことはPythonにやらせよう 第3版

Al Sweigart

Pythonクローリング&スクレイピング 増補改訂版

Pythonクローリング&スクレイピング 増補改訂版

加藤耕太

シゴトがはかどる Python自動処理の教科書

シゴトがはかどる Python自動処理の教科書

クジラ飛行机

私のおすすめからランダムで3冊を表示しています


最後に・・・

クラウドワークスココナラでお仕事受け付けています!

PythonとExcelを中心に仕事に役立つ業務ツールや自動化、スクレイピングツールの作成を受注していて、クラウドワークスでは気が付けば100件以上のお仕事を受注してきました!

会社員をやりながらの副業なので時間の捻出は相応ですが、クライアントの方々と近い立場でこちらからも提案しながら活動していますのでお悩みあれば是非ご相談ください

ココナラのプロフィールページへ

"ココナラ"に新規登録する際は1,000Pもらえる紹介コード使ってください

78E62K

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

VBAとPythonを中心にユーザー側でできるITを自己学習しているので備忘録半分、学習履歴を残して同じ道を辿る人の参考になればとブログを始めました

副業でスクレイピングツール作成を中心にできることを色々やっていますのでご相談いただけるとありがたいです!


クラウドワークスのページへ


ココナラのページへ

コメント

コメントする

目次