KeyError означает, что программа запросила у словаря ключ, которого в нём нет. Посмотрите имя ключа в последней строке traceback и сравните его с dictionary.keys(). Дальше выберите поведение по смыслу: обязательный ключ читайте через квадратные скобки и исправляйте входные данные, необязательный получайте через get, а наличие проверяйте оператором in. Не подставляйте значение по умолчанию, если отсутствие должно считаться ошибкой.
Ошибка часто появляется при чтении JSON, подсчёте элементов или обращении к настройкам: вчера поле name было во всех записях, а сегодня одна запись пришла без него. Ещё один частый случай проще: в словаре хранится user_name, а код просит username. Python не угадывает похожие написания и показывает отсутствующий ключ в кавычках.
Берём последнюю строку своего кода и точное представление отсутствующего ключа.
Проверяем тип объекта, keys(), регистр, пробелы и вложенность.
Обязательное поле исправляем, необязательное обрабатываем явно и предсказуемо.
Почему словарь выдаёт KeyError и что написано в traceback
Словарь сопоставляет уникальные хешируемые ключи со значениями. Выражение profile["city"] требует, чтобы ключ city существовал прямо сейчас. Если его нет, Python возбуждает KeyError. Последняя строка traceback обычно содержит сам ключ, а строка выше указывает место обращения. Наличие ключа не зависит от того, истинно ли его значение: ключ с None, нулём или пустой строкой всё равно существует.
| Словарь | Выражение | Результат |
|---|---|---|
{"name": "Ada"} | d["name"] | "Ada" |
{"name": "Ada"} | d["city"] | KeyError: city |
{"city": None} | "city" in d | True |
{"city": None} | d.get("city") | None |
{} | d.get("city", "не указан") | "не указан" |

Квадратные скобки требуют ключ, а get описывает запасной результат для допустимого отсутствия.
if d.get("score") считает отсутствием и ключ со значением 0. Для проверки структуры используйте if "score" in d.Находим ключ с помощью keys, repr и маленького примера
При диагностике не печатайте гигантский JSON целиком. Выведите тип объекта, ключи нужного уровня и точное представление подозрительной строки через repr. Оно показывает невидимые пробелы и разницу между строкой и числом. Вложенный словарь проверяйте по одному уровню, потому что одинаковый KeyError может возникнуть и на внешнем, и на внутреннем обращении.
profile = {
"name": "Ada",
"stats": {"score": 0},
"city ": "London",
}
requested = "city"
print(type(profile).__name__)
print(list(profile.keys()))
print(repr(requested))
print([repr(key) for key in profile])
if requested in profile:
print(profile[requested])
else:
print(f"Нет ключа {requested!r}")
# Безопасно читаем необязательное поле
language = profile.get("language", "не указан")
print(language)- Ключ
"city "содержит завершающий пробел и не равен"city". - Нулевой score существует, хотя в логическом условии само значение считается ложным.
- get позволяет явно задать подпись для действительно необязательного language.

Метод выбирают по смыслу отсутствия и по тому, должен ли словарь измениться.
Когда использовать скобки, get, setdefault и try except
Эти инструменты не взаимозаменяемы. Квадратные скобки честно сообщают о нарушении обязательной структуры. get удобен для необязательного чтения без изменения словаря. setdefault возвращает значение и одновременно создаёт отсутствующий ключ. try/except KeyError полезен, когда чтение является основной операцией и редкое отсутствие нужно обработать рядом.
| Инструмент | Когда подходит | Важная особенность |
|---|---|---|
d[key] | Ключ обязан существовать | Ошибка быстро раскрывает плохие данные |
key in d | Нужны разные ветки | Отличает отсутствие от ложного значения |
d.get(key, default) | Необязательное чтение | Не изменяет словарь |
d.setdefault(key, default) | Нужно создать контейнер | Изменяет словарь |
try/except KeyError | Редкое отсутствие при основном чтении | Обрабатывайте только узкий участок |
defaultdict | Много накоплений по новым ключам | Создаёт значение при обращении |
data.get("id", 0) создаст ложный заказ с id 0. Здесь лучше оставить явную ошибку или валидировать ответ.Практика: считаем слова без KeyError
Счётчик частот показывает разницу между чтением и созданием ключа. При первом появлении слова записи ещё нет, поэтому прямое увеличение counts[word] += 1 падает. Исправить можно через get, setdefault, defaultdict или Counter. Для начала полезно реализовать вариант с get: в нём явно виден старт с нуля.
- Возьмите строку
"код учит код проверяет код"и разделите её методомsplit(). - Создайте пустой словарь
counts = {}. - Для каждого слова выполняйте
counts[word] = counts.get(word, 0) + 1. - Проверьте результат: у слова «код» должно быть 3, у двух остальных слов по 1.
- Повторите задачу через обычный
if word in countsи сравните читаемость. - Добавьте нормализацию
lower()и удаление знаков препинания до подсчёта, не во время доступа к словарю.
- Новые слова получают начальное значение 0 и увеличиваются до 1 без исключения.
- Повторное слово использует существующее значение и в конце даёт 3.
- В коде видно, что отсутствие ключа для счётчика является нормальным первым состоянием.

Для счётчика новый ключ является нормальным состоянием и получает стартовое значение.
Почему KeyError возвращается после быстрого исправления
Обычно причина находится в границе данных: CSV содержит заголовок с пробелом, JSON имеет другую вложенность, пользователь ввёл разный регистр или один объект отличается от остальных. Без проверки схемы замена скобок на get лишь переносит ошибку в арифметику, шаблон или базу. Сначала сформулируйте, какие ключи гарантированы.
Следующая операция получает None и падает уже как TypeError или AttributeError, дальше от причины.
if d.get(key) путает отсутствие с 0, False, пустой строкой и пустым списком.
"Name", "name" и "name " являются тремя разными ключами.
Поле может находиться в data["user"]["name"], а не рядом с user. Проверяйте keys на каждом уровне.
Внутри может возникнуть другой KeyError. Оставьте в try только конкретное обращение, отсутствие которого ожидается.
Что показывает KeyError в последней строке?
Обычно точное представление ключа, который не найден в mapping.
Чем key in d отличается от d.get(key)?
in проверяет наличие, а get возвращает значение или default.
Изменяет ли get словарь?
Нет. setdefault и defaultdict могут создавать отсутствующие записи.
Почему if d.get("score") неверно для проверки ключа?
Значение 0 существует, но условие воспримет его как ложное.
Когда квадратные скобки лучше get?
Когда ключ обязателен и его отсутствие означает ошибку входных данных или программы.
Словари, циклы и функции собраны в курсе Python. Практикуйтесь на маленьких объектах в Кодике и каждый раз проговаривайте, какие ключи обязательны.
Дополните тему материалом о словарях Python простыми словами, затем разберите AttributeError и TypeError при смешивании строк и чисел.