Ошибка KeyError в Python означает, что в словаре нет ключа, к которому обратилась программа. Ключ в кавычках — KeyError: 'email' — это уже подсказка: сверь его написание, регистр и тип, найди место добавления и проверь, откуда пришли данные. В большинстве случаев исправление занимает одну-две строки, а try/except нужен далеко не всегда.
Коротко: как исправить KeyError?
- Прочитай ключ в кавычках в последней строке traceback.
- Сверь написание ключа буква в букву, включая регистр:
"email","Email"и"e-mail"— разные ключи. - Проверь тип: строка
"1"и число1— это разные ключи. - Убедись, что ключ добавлен в словарь до строки, где он читается.
- Если ключ может отсутствовать, читай через
.get()или проверяй наличие черезin. - Для данных извне (JSON, ответ API, файл) проверяй обязательные поля отдельно.
Кот-наставник— У
KeyErrorполезная привычка: он всегда называет виновника прямо в кавычках —'email'. Не начинай с переписывания программы, сначала найди, почему именно этого ключа не оказалось в словаре.
Что означает KeyError в Python?
KeyError — исключение, которое Python вызывает, когда в отображении не находится ключ, к которому обратился код. Чаще всего отображение — это словарь
dict, но то же поведение есть уdefaultdict,OrderedDictи похожих коллекций.Сообщение
KeyError: 'email'переводится как «ошибка ключаemail»: Python искал в словаре ключ"email"и не нашёл.
user = {"name": "Анна", "city": "Казань"}
print(user["email"])Ошибка выполнения — main.py, строка 2
KeyError: 'email'
Словарь ищет ключ напрямую и целиком, а не перебором по порядку. Список хранит элементы по номерам, поэтому несуществующий номер там — это IndexError. Словарь отвечает по ключу, поэтому несуществующий ключ — это KeyError. Как устроены словари, методы и перебор, разобрано в статье «Словари в Python: создание, методы и перебор».
Почему возникает KeyError?
| Что видно в коде | Что произошло | Что проверить |
|---|---|---|
| user["emial"] вместо user["email"] | Опечатка в ключе | Каждый символ ключа |
| user["Email"] при ключе "email" | Другой регистр | Регистр букв |
| data[1] при строковых ключах "1" | Другой тип ключа | Кавычки и тип данных |
| Ключ читается выше добавления | Нужная строка ещё не выполнилась | Порядок выполнения |
| Ключ есть в одном словаре, но нет в другом | Не тот источник данных | Откуда пришёл словарь |
| Поле отсутствует в JSON-ответе | Внешние данные без поля | Проверку полей |
1. Опечатка или другой регистр
config = {"timeout": 30, "retries": 3}
print(config["time_out"])Ошибка выполнения — main.py, строка 2
KeyError: 'time_out'
Ключ сравнивается целиком и с учётом регистра. "timeout" и "time_out" — разные строки, поэтому второго ключа в словаре нет. Это самая частая причина KeyError: не сверяй ключ беглым взглядом, а сравни символ за символом, как при отладке NameError с именами переменных.
2. Строка и число — разные ключи
statuses = {"1": "новый", "2": "в работе"}
print(statuses[1])Ошибка выполнения — main.py, строка 2
KeyError: 1
В словаре ключ — строка "1", а код ищет число 1. Для Python это разные значения, и такой ключ не находится. Ловушка типична для двух мест: input() всегда возвращает строку, а ключи в JSON-файлах после json.loads() тоже строки. Преобразование int("1") и обратное str(1) разобраны в статье «Типы данных в Python: полный гайд для начинающих».
3. Ключ читается раньше, чем появляется
prices = {}
print(prices["coffee"])
prices["coffee"] = 150Ошибка выполнения — main.py, строка 2
KeyError: 'coffee'
prices = {"coffee": 150}
print(prices["coffee"])150
Python выполняет код сверху вниз. Когда первая строка читает prices["coffee"], словарь ещё пуст: присваивание ниже не выполнилось. Исправление — в порядке строк: сначала заполни словарь, потом читай из него. Та же логика действует, если ключ добавляется только внутри ветки if или цикла: проверь, что нужный путь выполнения действительно сработал.
4. Поле отсутствует в данных извне
import json
response = json.loads('{"user": {"name": "Анна"}}')
print(response["user"]["email"])Ошибка выполнения — main.py, строка 4
KeyError: 'email'
Во вложенных структурах ключ проверяется на каждом уровне. Ключ "user" нашёлся, но внутри вложенного словаря нет "email" — ошибка всё равно возникнет. Ответы API и JSON-файлы часто приходят без необязательных полей, поэтому доступ к ним нужно строить с учётом отсутствия.
Как исправить KeyError?
Способ исправления зависит от одного вопроса: ключ обязан быть в словаре или его отсутствие — нормальная ситуация?
Если ключ обязан быть, а его нет — это дефект самого кода. Исправь опечатку, регистр, тип или порядок строк из раздела выше, но не глуши ошибку обработчиком.
Если ключа может не быть, есть два честных способа чтения. Первый — метод .get() со значением по умолчанию:
user = {"name": "Анна", "city": "Казань"}
email = user.get("email", "не указан")
print(email)не указан
Второй — явная проверка через оператор in:
user = {"name": "Анна", "city": "Казань"}
if "email" in user:
print(user["email"])
else:
print("email не указан")email не указан
Правило простое: квадратные скобки user["email"] — для ключей, которые обязаны существовать, а .get() или in — для тех, что могут отсутствовать. Подробное сравнение [] и .get() с интерактивными примерами есть в статье про словари.
Когда try/except уместен, а когда нет?
try/except KeyError уместен в другой ситуации: когда словарь пришёл извне и необязательное поле действительно может отсутствовать.
import json
response = json.loads('{"user": {"name": "Анна"}}')
try:
email = response["user"]["email"]
except KeyError:
email = "не указан"
print(email)не указан
Граница применимости простая: обрабатывай предусмотренное отсутствие во внешних данных и не маскируй опечатку в собственном коде. Для собственных словарей ошибка KeyError почти всегда означает баг, который нужно найти и исправить, а не спрятать.
Где та же логика сломает код снова?
- После
del user["email"]ключ удаляется. Следующее обращение кuser["email"]снова дастKeyError. - Ключ, добавленный только в одной ветке
if, может отсутствовать на другом пути выполнения. - Проверка на верхнем уровне не защищает вложенные словари:
"user" in responseне гарантирует наличиеresponse["user"]["email"]. - Один и тот же код на другом источнике данных может упасть, если там другая структура полей.
- После чтения JSON строковые ключи остаются строками: число
1и строка"1"по-прежнему разные ключи.
KeyError, NameError, IndexError и AttributeError — в чём разница?
| Ошибка | Чего не нашёл Python? | Пример |
|---|---|---|
| KeyError | Ключа в словаре | user["email"] |
| NameError | Доступного имени целиком | print(total) |
| IndexError | Элемента списка по номеру | numbers[10] |
| AttributeError | Атрибута справа от точки | user.emial |
Границы видны по форме обращения: скобки с ключом — словарь, скобки с числом — список, имя без точки — переменная или функция, часть после точки — атрибут. Разбор механики поиска имени и её исправление — в статье «NameError: name is not defined в Python — как исправить». Про выход за границы списка — в статье «IndexError: list index out of range в Python».
Короткие ответы про KeyError
Что означает KeyError в Python?
«Ошибка ключа». Python обратился к словарю по ключу, которого в нём нет. Ключ, который не удалось найти, указан в кавычках: KeyError: 'email'.
Как исправить KeyError: 'ключ'?
Прочитай ключ в кавычках и проверь четыре вещи: написание и регистр, тип ключа (строка или число), порядок выполнения (добавлен ли ключ до чтения) и источник данных. Если ключ может отсутствовать, читай через .get() или проверяй через in.
Чем KeyError отличается от IndexError?
KeyError относится к словарю и несуществующему ключу, IndexError — к списку или строке и несуществующему номеру. Словарь отвечает по ключу, список — по позиции.
Как проверить, есть ли ключ в словаре Python?
Оператором in: if "email" in user:. Или методом .get(), который возвращает None или заданное значение по умолчанию, если ключа нет.
Почему возникает KeyError: 1, хотя в словаре есть "1"?
Потому что 1 — это число, а "1" — строка. Python считает их разными ключами. Проверь тип: ключи из input() и из JSON — строки, а в коде могло остаться число.
Главное про KeyError:
- Ключ в кавычках — отправная точка
Python прямо указывает ключ, которого не нашёл. Начинай диагностику с него, а не со всего словаря.
- Причин всего четыре
Написание и регистр, тип ключа, порядок выполнения и источник данных. Проверь их по очереди — обычно хватает одной из них.
- Способ чтения зависит от контракта
Ключ обязан существовать — квадратные скобки. Ключ может отсутствовать —
.get()или проверка черезin. - Вложенные структуры проверяются на каждом уровне
Наличие внешнего ключа не гарантирует наличие внутреннего.
- Обработчик не заменяет исправление
try/except KeyError— для предусмотренного отсутствия во внешних данных, а не для сокрытия опечатки в своём коде.
Кот-наставник— Прежде чем лезть в код, прочитай ключ в кавычках и задай один вопрос: этот ключ обязан быть в словаре или его отсутствие — нормальная ситуация? Ответ подскажет, чинить ли сам код или выбирать
.get().
Разберись с KeyError на практике!
На SkillPy ты создаёшь словари и читаешь значения по ключу, а AI-наставник объясняет именно твою ошибку: почему ключа нет и когда брать .get() вместо скобок. Первые задачи доступны бесплатно.
