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期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?