Как исправить ошибку KeyError в Python?

Я пишу программу на Python и при запуске вижу сообщение KeyError. Как это исправить?

Исключение KeyError — это ошибка, которую видят многие программисты, когда начинают использовать словари Python.

Для понимания этой ошибки важны следующие моменты:

  • Значение KeyError Python
  • Как исправить ключевые ошибки
  • Как обрабатывать ключевые ошибки

Что означает KeyError?

KeyError — это способ для Python сообщить вам, что вы пытаетесь получить доступ к ключу, которого нет в словаре.

В качестве примера создайте файл с именем keyerror.py:

  • создать словарь, содержащий страны и их столицы.
  • напечатайте столицу Италии.
  • затем напечатайте столицу Франции.
countries = {'Italy': 'Rome', 'Poland': 'Warsaw', 'UK': 'London'}

print(countries['Italy'])
print(countries['France'])

При выполнении этого кода Python вызывает исключение KeyError:

Rome
Traceback (most recent call last):
  File "keyerror.py", line 3, in <module>
    print(countries['France'])
KeyError: 'France'

Как видите, значение первого ключа в словаре (Италия) печатается правильно. Но KeyError возникает при втором операторе печати.

Python выдает ошибку KeyError при попытке доступа к ключу, которого нет в словаре.

В данном случае ключа «Франция» в словаре нет countries.

Обратите внимание также на то, как Python сообщает, в какой строке кода произошло исключение. Это очень полезно для быстрого поиска причины ошибки, когда вам нужно просмотреть сотни или тысячи строк кода.

Основной навык: Когда Python вызывает исключение, включается трассировка. Трассировка дает вам все необходимые детали для понимания типа исключения и поиска того, что вызвало его в вашем коде.

Как исправить KeyError в Python?

Если ваша программа проста, есть два основных способа исправления ключевой ошибки:

  1. Избегайте ссылок на ключ, которого нет в словаре.
  2. Добавьте недостающий ключ в словарь

Однако эти подходы не являются надежными и не предотвращают повторение подобной ошибки.

Давайте вместо этого рассмотрим два других варианта:

Первый вариант

Сообщите Python не возвращать KeyError при попытке доступа к ключу, которого нет в словаре, а вместо этого возвращать значение по умолчанию.

Допустим, вы хотите вернуть значение по умолчанию ‘Unknown’ для любых ключей, отсутствующих в словаре. Вот как это можно сделать с помощью метода dictionary get():

countries = {'Italy': 'Rome', 'Poland': 'Warsaw', 'UK': 'London'}
default = 'Unknown'

print(countries.get('Italy', default))
print(countries.get('France', default))

Вывод становится следующим:

Rome
Unknown

Таким образом, по крайней мере, таким образом вы получаете больше контроля над выводом, возвращаемым вашей программой.

Второй вариант

Проверьте, существует ли ключ в словаре, с помощью оператора in, который возвращает логическое значение (True или False) на основе существования этого ключа в словаре.

В примере ниже мы используем оператор in вместе с оператором if-else для проверки существования ключа перед доступом к его значению:

countries = {'Italy': 'Rome', 'Poland': 'Warsaw', 'UK': 'London'}

if 'France' in countries:
    print("The capital of France is %" % countries['France'])
else:
    print("The capital of France is unknown")

Вот что получилось:

The capital of France is unknown

Это тоже хороший вариант!

Как обрабатывать KeyError?

В предыдущем разделе мы представили метод словаря get() для возврата значения по умолчанию, если ключ отсутствует в словаре.

Но что произойдет, если вы не передадите значение по умолчанию в качестве второго аргумента методу get()?

countries = {'Italy': 'Rome', 'Poland': 'Warsaw', 'UK': 'London'}

print(countries.get('Italy'))
print(countries.get('France'))

Знаете, какой результат?

Rome
None

Интересно, что на этот раз Python не вызывает исключение KeyError, поскольку метод get() возвращает None, если ключ отсутствует в словаре.

Это означает, что вы можете реализовать условную логику в своем коде на основе значения, возвращаемого методом get(). Вот пример:

countries = {'Italy': 'Rome', 'Poland': 'Warsaw', 'UK': 'London'}
  
capital = countries.get('France')

if capital:
    print("The capital is %s" % capital)
else:
    print("The capital is unknown")

Вывод:

The capital is unknown

Хороший способ избежать этого исключения.

Избежание ошибки KeyError с помощью цикла for

KeyError возникает, когда вы пытаетесь получить доступ к ключу, которого нет в словаре. Это означает, что вы можете предотвратить KeyError, убедившись, что вы получаете доступ только к тем ключам, которые есть в словаре.

Вы можете сделать это, используя цикл for, который проходит по всем ключам словаря. Это гарантирует, что вы ссылаетесь только на те ключи, которые присутствуют в словаре.

Давайте рассмотрим один пример:

countries = {'Italy': 'Rome', 'Poland': 'Warsaw', 'UK': 'London'}

for key in countries:
    print("The capital of %s is %s" % (key, countries[key]))

Вывод:

The capital of Italy is Rome
The capital of Poland is Warsaw
The capital of UK is London

Вы можете использовать цикл for, чтобы пройти по всем ключам в словаре и убедиться, что вы не обращаетесь к ключам, которых нет в словаре. Это предотвращает возникновение исключения Python KeyError.

Как обработать исключение KeyError, если оно возникло?

Универсальный подход, который вы можете использовать с любыми исключениями, — это блок try-except. Это позволяет вам обрабатывать исключение чистым способом с помощью блока except.

Вот как это применимо к нашему примеру:

countries = {'Italy': 'Rome', 'Poland': 'Warsaw', 'UK': 'London'}
  
try:
    print('The capital of France is %s' % countries['France'])
except KeyError:
    print('The capital of France is unknown')

В этом примере блок except написан специально для обработки исключения KeyError. Мы могли бы также использовать общее исключение, удалив KeyError.

try:
    print('The capital of France is %s' % countries['France'])
except:
    print('The capital of France is unknown')

Итак, нужно ли нам указывать тип исключения?

Это может быть удобно, если блок try может вызывать несколько типов исключений и мы хотим обрабатывать каждое исключение по-разному.