Python 3.15 で CSV が文字化けする3つの形|Excel で崩れる原因と直し方を実機で確かめました

Python

昨日まで動いていた Python のプログラムが、CSV を読むところで急に止まった。Python が書き出した CSV を Excel で開くと、読めない文字が並んでいる。どちらも、原因はプログラムの書き間違いではないかもしれません。

事務さん
事務さん

月末の集計のプログラムが、今朝から止まるんです。何も変えていないのに……。

よろずちゃん
よろずちゃん

Python を 3.15 に上げませんでしたか? CSV の読み書きの動きが変わったんです。順に見ていきましょう。

2026年10月9日に公開された Python 3.15 で、文字コードの初期設定が変わりました。同じコードでも、3.14 と 3.15 では読み書きの結果が変わります。この記事では、Windows の Excel と Python 3.14.7・3.15.2 で実際に試した結果と、直し方をまとめます。

先に結論

変わったこと:open() で encoding を書かないときの文字コードが、Windows の cp932 から UTF-8 に変わりました。

こわいのは書くとき:読むときはエラーで止まります。書くときと行を足すときは、エラーが出ないまま Excel で化けます。

直し方は1つ:encoding を書きます。Excel の CSV を読むなら cp932、Excel で開く CSV を書くなら utf-8-sig です。

# Excel で保存した「CSV」を読む
open("kiroku.csv", newline="", encoding="cp932")

# Excel で開く CSV を書く
open("kiroku.csv", "w", newline="", encoding="utf-8-sig")

いま困っている症状から読むなら、次の表の場所へどうぞ。

症状読むところ
UnicodeDecodeError で止まるCSV が読めない
Python が書いた CSV が Excel で化けるExcel で化ける
最後に足した行だけ化ける足した行だけ化ける
見出しの列が見つからない(KeyError)見えない文字が残る
pandas を使っているpandas の場合

自分の Python の版は、次のコマンドで確かめられます。

python --version

何が変わったのか

ファイルを開くとき、文字コードを書かないと、Python は初期設定の文字コードを使います。日本語の Windows では、3.14 まで cp932 でした。3.15 からは UTF-8 です。

Python 3.14 まで

encoding なし → cp932

Excel の「CSV」と同じ

Python 3.15 から

encoding なし → UTF-8

Excel の「CSV」と違う

公式の説明は What’s New In Python 3.15 にあります。互換性のために、encoding を必ず書くことも勧めています。

Excel で保存したときの文字コードも確かめました。Excel の「CSV」は cp932、「CSV UTF-8」は BOM(ファイルの先頭に付く印)つきの UTF-8 でした。つまり、Excel でふつうに保存した「CSV」と、3.15 の初期設定が、食い違うようになりました。

CSV が読めない:UnicodeDecodeError

まず、CSV を1行ずつ表示するだけのコードです。encoding を書いていません。

import csv

with open("kiroku.csv", newline="") as f:
    for row in csv.reader(f):
        print(row)

cp932 の kiroku.csv を読むと、3.14 では読めました。同じコードを 3.15 で動かすと、次のエラーで止まります。

UnicodeDecodeError: 'utf-8' codec can't decode byte 0x93 in position 0: invalid start byte

エラーの 'utf-8' は「UTF-8 として読もうとしたら、読めなかった」という意味です。cp932 のファイルなので、そう書きます。

with open("kiroku.csv", newline="", encoding="cp932") as f:

この1か所を直すと、3.14 でも 3.15 でも読めました。

shift_jis ではなく cp932

encoding="shift_jis" と書く例も見かけますが、「①番の棚」を入れた CSV は、shift_jis ではエラーで止まりました。cp932 なら読めました。Windows で作った CSV は cp932 と書くのが安全です。

反対に、エラーに 'cp932' と出るときは、ファイルが UTF-8 かもしれません。encoding="utf-8-sig" を試します。BOM があってもなくても読めました。

Excel で化ける:3.15 が書いた CSV

次は書くほうです。この形が、エラーが出ないぶん気づきにくくなります。

import csv

rows = [
    ["日付", "品目", "金額"],
    ["2026-11-01", "コーヒー豆", 1200],
    ["2026-11-02", "東京都の切手", 840],
    ["2026-11-03", "請求書の封筒", 300],
]

with open("kiroku.csv", "w", newline="") as f:
    csv.writer(f).writerows(rows)

3.14 で動かしてできた CSV を、Excel で開きました。

Python 3.14 が書いた CSV を Excel で開いた表。日本語が正しく表示されている
Python 3.14 が書いた CSV。Excel の表の部分を画像に書き出しました。

同じコードを 3.15 で動かすと、こうなります。エラーは何も出ません。

Python 3.15 が書いた CSV を Excel で開いた表。日本語が化け、3列あった表の多くの行が2列に崩れている
Python 3.15 が書いた CSV。文字が化けるだけでなく、金額が C 列に残ったのは3行目だけです。

化けた文字がカンマを飲み込むので、列まで崩れます。ただ、いつも崩れるわけではありません。試しに25個の語を「語,100」の形で書いて Excel で開くと、11語は列が崩れ、14語は2列のままでした。

Excel で開く CSV なら、utf-8-sig と書きます。

with open("kiroku.csv", "w", newline="", encoding="utf-8-sig") as f:

3.14 でも 3.15 でも同じファイルになり、Excel で正しく開けました。

CSV を渡す相手書き方気をつけること
Excel で開く人utf-8-sigいちばん無難です
文字コードの決まりがある仕組み相手の決まりに合わせるcp932 と決まっていれば cp932
cp932 で書くとき

cp932 では絵文字を書けません。「とても良い😀」を書くと UnicodeEncodeError で止まりました。utf-8-sig なら書けました。

足した行だけ化ける:いちばん気づきにくい形

事務さん
事務さん

記録のファイルは開けるんです。でも、今朝足した行だけ文字がおかしくて。

よろずちゃん
よろずちゃん

それがいちばん気づきにくい形です。エラーが出ないまま、1つのファイルに2つの文字コードが混ざります。

毎日1行ずつ足していく記録の CSV は、とくに注意が要ります。3.14 で作った kiroku.csv に、3.15 で次のコードを動かしました。

import csv

with open("kiroku.csv", "a", newline="") as f:
    csv.writer(f).writerow(["2026-11-04", "東京都の切手", 840])

エラーは出ません。Excel で開くと、足した行だけが化けています。

Excel で開いた表。1行目から4行目は正しく、最後に足した5行目の品目だけが化けている
5行目だけが化けています。1つのファイルの中に、cp932 の行と UTF-8 の行が混ざった状態です。

このファイルは、encoding="cp932" でも encoding="utf-8" でも、最後まで読めませんでした。3.14 の指定なしでも 3.15 の指定なしでも止まります。何日も気づかないと、化けた行が増えていきます。

「順に試す」でも安心できない

文字コードが分からないときに、utf-8-sig がだめなら cp932、と順に試す書き方があります。ふつうのファイルには便利ですが、混ざったファイルには向きません。

cp932 の見出しのあとに、UTF-8 の行を1行足して試しました。語を25個入れ替えると、11語は止まり、14語はエラーなしで読めてしまいました。「読めた」と表示されても、足した行は化けたままです。読めたあとは、中身を見てください。

混ざったファイルを直す

1行ずつ、まず UTF-8 で読み、だめなら cp932 で読み直して、utf-8-sig で別のファイルに保存します。

from pathlib import Path

src = Path("kiroku.csv")            # 混ざってしまったファイル
dst = Path("kiroku_naoshita.csv")   # 直したあとのファイル(元は残す)

lines = []
for raw in src.read_bytes().splitlines():
    try:
        lines.append(raw.decode("utf-8"))
    except UnicodeDecodeError:
        lines.append(raw.decode("cp932"))

dst.write_text("\r\n".join(lines) + "\r\n", encoding="utf-8-sig", newline="")
print(len(lines), "行を書きました")
直したあとの CSV を Excel で開いた表。5行すべて正しく表示されている
直したあとの CSV。5行とも元に戻りました。
必ず写しで

行ごとの判定は、いつも当たるとは限りません。日本語の語を15個試したときは、cp932 の語を UTF-8 と取り違えることはありませんでしたが、すべての文字を確かめたわけではありません。元のファイルは残し、直したあとの中身を目で見てください。1行の中で文字コードが混ざったファイルは、この方法では直りません。

見えない文字が残る:KeyError

Excel の「CSV UTF-8」は、先頭に BOM が付きます。これを encoding="utf-8" で読むと、エラーは出ませんが、1列目の見出しの前に見えない文字が残ります。

見出し ['日付', '品目']
KeyError: '日付'

画面では「日付」に見えるのに、row["日付"] が見つからないのは、この形です。3.15 では、encoding を書かずに読んでも同じことが起きます。encoding="utf-8-sig" で読むと、見えない文字は残りません。

pandas の場合

read_csv と to_csv の動きは、Python 3.14.7(pandas 3.0.5)と Python 3.15.2(pandas 3.1.0)で同じでした。データ分析の基本はpandas の入門記事にまとめています。

やること結果
read_csv で UTF-8 を読む指定なしで読める(BOM つきも)
read_csv で Excel の「CSV」を読む指定なしは止まる。encoding="cp932" で読める
to_csv で書く指定なしは BOM なしの UTF-8

pandas だけのコードは、3.15 にしても変わりません。ただ、to_csv は 3.15 より前から BOM なしの UTF-8 で書きます。Excel で開くなら、df.to_csv("kiroku.csv", index=False, encoding="utf-8-sig") と書いてください。

例外は、open() で開いたファイルを pandas に渡す形です。この形だけは 3.14 が cp932、3.15 が UTF-8 と変わりました。

3.15 に上げる前にしておくこと

encoding を書いていない所を探す

3.14 のまま、次のように動かすと、encoding がない所を教えてくれます。ふつうに動かしても、この警告は出ません。

python -X warn_default_encoding kaku.py
kaku.py:10: EncodingWarning: 'encoding' argument not specified
  with open("kiroku.csv", "w", newline="") as f:

出た場所に、そのファイルの文字コードを書いていきます。動かした所しか警告は出ないので、ふだん通らない処理も動かしてみてください。

急ぎのときは、元の動きに戻す

今日の仕事を止められないときは、3.15 のまま前の動きに戻せます。PowerShell なら次のとおりです。

$env:PYTHONUTF8 = "0"
python yomu.py

1回だけなら python -X utf8=0 yomu.py でも同じでした。どちらも 3.15 で cp932 の CSV を読めました。ただ、これは一時しのぎです。別のパソコンで動かすとまた止まるので、あとで encoding を書いてください。

早見表:どの読み方で読めたか

ファイル3.14 指定なし3.15 指定なしcp932utf-8utf-8-sig
Excel の「CSV」(cp932)読める止まる読める止まる止まる
UTF-8(BOM なし)止まる読める止まる読める読める
Excel の「CSV UTF-8」(BOM つき)止まる文字が残る止まる文字が残る読める

「文字が残る」は、1列目の見出しの前に見えない文字が残ることです。この表は4行の試しのファイルの結果です。中身によっては、「止まる」所がエラーなしで化けて読めることがあります。

よくある質問

3.15 に上げないほうがいいですか

急いで上げる必要がないなら、encoding を書いてから上げるのが安全です。3.14 も、3.15 と同じ10月25日に新しい版(3.14.10)が出ていました。これから始める人は、最初から encoding を書く形で覚えれば、3.15 で始められます。始め方はインストールとエディタの準備にまとめています。

errors=”ignore” を付ければ止まりませんか

止まりませんが、勧めません。混ざったファイルを encoding="utf-8", errors="ignore" で読むと、エラーは消えた代わりに、cp932 の行の日本語が失われました。止まらないだけで、データは直っていません。

家計簿の CSV も直す必要がありますか

encoding が書いてあれば、3.15 でも変わりません。家計簿を自動集計する記事のように、読むときに文字コードを書いているコードは、この変更の影響を受けません。

まとめ

  • Python 3.15 で、encoding を書かないときの文字コードが UTF-8 に変わりました。
  • 読むときはエラーで止まります。書くときと足すときは、エラーなしで Excel で化けます。
  • Excel の「CSV」を読むなら cp932、Excel で開く CSV を書くなら utf-8-sig です。
  • 行を足す CSV は、Python を上げる前に encoding を書いてください。
  • 混ざったファイルは1行ずつ読み直して戻せることがあります。必ず写しで試してください。
事務さん
事務さん

行を足すプログラムには、今日のうちに encoding を書いておきます。

よろずちゃん
よろずちゃん

はい。書いておけば、3.14 でも 3.15 でも同じ動きになります。混ざったファイルを直すときは、写しで試してくださいね。

確かめていないこと

  • Mac・Linux では試していません。この記事の「3.14 まで cp932」は日本語の Windows の話です。
  • Excel は「開く」と「保存」だけを試しました。データの取り込みの機能は試していません。
  • Excel の版は1つだけです。古い版の Excel では試していません。
  • 列が崩れる語の数は、選んだ25語の結果です。すべての語の割合ではありません。
  • 文字コードを自動で見分けるライブラリは比べていません。

検証した環境:Windows 11 / Python 3.14.7(pandas 3.0.5)/ Python 3.15.2(pandas 3.1.0)/ Excel 16.0。試し用の CSV は Python で作りました。記事のコードは 3.14.7 と 3.15.2 の両方で動かしています(2026年11月4日)。

コメント

タイトルとURLをコピーしました