- Python
Python KeyErrorの原因と直し方|dictとpandas
KeyError: 'email' は、dict(辞書)や pandas の DataFrame に、存在しないキー・列名でアクセスしたときのエラーです。 エラー文の 'email' が、探したのに見つからなかったキーです。
まず、実際にどんなキーがあるかを表示して、探したキーと見比べます。
print(list(user.keys())) # dict
print(list(df.columns)) # pandas
print([repr(c) for c in df.columns]) # 前後の空白や見えない文字まで表示
| 見比べた結果 | 原因 | 直し方 |
|---|---|---|
| 本当に無い | データにそのキーが無いことがある | get・in で無いときの扱いを決める |
'name '(後ろに空白) |
CSV の見出しに空白 | 列名を strip() |
'Price' と 'price' |
大文字小文字の違い | 列名を lower() |
'id' |
CSV の先頭の BOM | encoding="utf-8-sig" で読む |
'1' と 1 |
JSON を通すと数値のキーが文字列になる | 文字列のキーで引く |
確認環境:Python 3.11、pandas 2.2.3・3.0.6(確認日 2026年10月11日)。pandas の結果は、2つの版で同じでした。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Python KeyErrorの原因と直し方|dictとpandas」
dict の KeyError
無いかもしれないキーは get か in
user = {"name": "佐藤", "age": 30}
user["email"] # KeyError: 'email'
user.get("email") # None
user.get("email", "未登録") # '未登録'
"email" in user # False
| 書き方 | キーが無いとき | 向いている場面 |
|---|---|---|
d[key] |
KeyError | 必ずあるはずのキー(無ければ不具合として止めたい) |
d.get(key) |
None |
無いことがあるキー |
d.get(key, 既定値) |
既定値 | 既定値が決まっているとき |
key in d |
False |
あるかどうかで処理を分けたいとき |
何でも get にすればよいわけではありません。 必ずあるはずのキーが無いのは、データの不具合です。get で None にすると、その先で別のエラー('NoneType' object is not subscriptable など)になり、原因が分かりにくくなります。
集計の += で出る
cnt = {}
for w in ["a", "b", "a"]:
cnt[w] += 1 # KeyError: 'a'(まだ cnt['a'] が無い)
from collections import defaultdict
cnt = defaultdict(int) # 無いキーは 0 から始まる
for w in ["a", "b", "a"]:
cnt[w] += 1
# {'a': 2, 'b': 1}
cnt[w] = cnt.get(w, 0) + 1 でも書けます。数えるだけなら collections.Counter も使えます。リストに追加していくなら d.setdefault(key, []).append(値) です。
JSON を通すと、数値のキーが文字列になる
d = json.loads(json.dumps({1: "a", 2: "b"}))
d[1] # KeyError: 1
d["1"] # 'a'
JSON のオブジェクトのキーは必ず文字列なので、保存して読み込み直すと、1 が "1" になりました。API のレスポンスやキャッシュから読んだ dict で、数値で引いて失敗するのはこのためです。エラー文が KeyError: 1(引用符なし)なら数値、KeyError: '1' なら文字列で探しています。
環境変数(os.environ)
os.environ["API_KEY"] # KeyError: 'API_KEY'
os.environ.get("API_KEY") # None
os.getenv("API_KEY", "なし") # 'なし'
環境変数が設定されていないと KeyError になります。必須の設定なら、起動時に分かりやすいメッセージで止めます。
api_key = os.environ.get("API_KEY")
if not api_key:
raise RuntimeError("環境変数 API_KEY を設定してください")
pandas の KeyError(列名)
id,name ,Price ← 見出し(name の後ろに空白、Price は大文字)
1,佐藤,100
2,鈴木,200
df = pd.read_csv("bom.csv")
print(list(df.columns)) # ['id', 'name ', 'Price']
df["name"] # KeyError: 'name'
df["price"] # KeyError: 'price'
見た目は同じでも、'name '(後ろに空白)と 'name' は別の列名です。 print(df.columns) では空白が見えにくいので、repr で表示します。
print([repr(c) for c in df.columns]) # ["'id'", "'name '", "'Price'"]
列名をまとめてそろえる
df.columns = df.columns.str.strip().str.lower()
print(list(df.columns)) # ['id', 'name', 'price']
df[["id", "name", "price"]] # OK
読み込んだ直後に列名をそろえておくと、以降のコードで列名の揺れを気にしなくてよくなります。
複数の列を指定したとき
df[["id", "name"]]
# KeyError: "['name'] not in index"
見つからなかった列だけが [...] で表示されます。 行の指定(df.loc[5])で無い番号を指定したときも KeyError: 5 になります。
csv モジュールでは BOM が付いたキーになる
Excel で「CSV UTF-8」として保存したファイルなどは、先頭に BOM(見えない3バイト)が付いています。
with open("bom.csv", encoding="utf-8", newline="") as f:
r = csv.DictReader(f)
print(r.fieldnames) # ['id', 'name ', 'Price'] ← 先頭の列名に
row = next(r)
row["id"] # KeyError: 'id'
with open("bom.csv", encoding="utf-8-sig", newline="") as f: # utf-8-sig で読む
r = csv.DictReader(f)
print(r.fieldnames) # ['id', 'name ', 'Price']
csv モジュールで utf-8 として読むと、最初の列名が 'id' になり、row["id"] が KeyError になりました。 utf-8-sig で読むと、先頭の BOM を読み飛ばします(Python 公式ドキュメント)。
一方、pandas の read_csv は、encoding="utf-8" でも BOM を取り除いて 'id' として読みました(確認した2つの版とも)。pandas では問題なく、csv モジュールに書き換えたとたんに出る、ということがあります。
| 読み方 | BOM 付き CSV の最初の列名 |
|---|---|
csv モジュール + encoding="utf-8" |
'id'(KeyError の原因) |
csv モジュール + encoding="utf-8-sig" |
'id' |
pandas read_csv(utf-8) |
'id' |
確認の手順(チェックリスト)
| 順番 | 確認すること | 方法 |
|---|---|---|
| 1 | 探したキー | エラー文の '...'(引用符なしなら数値) |
| 2 | 実際のキー・列名 | list(d.keys())、[repr(c) for c in df.columns] |
| 3 | 空白・大文字小文字 | 列名を str.strip().str.lower() でそろえる |
| 4 | '' が付いていないか |
csv モジュールは encoding="utf-8-sig" |
| 5 | JSON を通したデータか | 数値のキーは文字列になる |
| 6 | 無いことがあるキーか | get・in・defaultdict。必須なら分かりやすく止める |
よくある質問
Q. try / except KeyError で囲めばよいですか。
A. 無いことがある前提の処理なら、get や in のほうが意図が伝わります。except KeyError は、範囲を広く囲むと、別のキーの KeyError まで隠してしまいます。使うなら、そのキーを読む1行だけを囲みます。
Q. pandas で列が無いときに None を返したいです。
A. df.get("name") は、列が無ければ None を返します。確認環境でも、列名が 'name ' のときに df.get("name") は None でした。
まとめ
- 探したキーが無いエラー。まず
list(d.keys())・reprで実際のキーを見る - dict は
get・in・defaultdictで無いときの扱いを決める。必須のキーは無理に隠さない - JSON を通すと数値のキーは文字列。
KeyError: 1か'1'かで見分ける - pandas は列名の空白・大文字小文字。読み込み直後に
strip().lower()でそろえる - csv モジュールは BOM で
'id'になる。utf-8-sigで読む(pandas は自動で外す)
参考・出典
確認日はいずれも 2026年10月11日です。
- Python ドキュメント「codecs」(encodings.utf_8_sig):https://docs.python.org/3/library/codecs.html#module-encodings.utf_8_sig
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Python KeyErrorの原因と直し方|dictとpandas」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。