The Python Programming Guide

Обработка исключений и ошибок

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

В Python ошибки можно разделить в целом на два вида:

Про второй вид ошибок в основном и пойдет дальнейший материал.

Конструкция try-except

Конструкция try-except позволяет “поймать” возникающую ошибку в программе. При этом Python продолжает выполнение программой дальше.

Полный синтаксис:

try:
    <инструкции>
except <тип исключения>:
    <инструкции>
else:               # опционально
    <инструкции>
finally:            # опционально
    <инструкции>

Пример:

try:
    print(unknown)

except:
    print("Вызвано исключение")
Вызвано исключение

В данном примере исключение вызывается в связи с тем, что переменная unknown не определена.

Множественные исключения

Блоков except можно определить бесконечно много, если того требует логика программы. Такой подход часто используется, когда заранее известны вызываемые исключения.

Пример с исключением NameError, которое вызывается при неопределённой переменной:

try:
    print(unknown)
except NameError:
    print("Переменная unknown не определена")
except:
    print("Произошло что-то еще")
Переменная unknown не определена

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

try:
    number = int("not-number")
except (NameError, ValueError) as e:
    print(type(e), e)
except:
    print("Произошло что-то еще")
<class 'ValueError'> invalid literal for int() with base 10: 'not-number'

Заметка

С помощью ключевого слова as можно присвоить переменной значение объекта, который был создан при вызове исключения. В примере выше переменной e присваивается экземпляр класса NameError или ValueError в зависимости от вызванной ошибки.

Блок else

Блок else, следующий за try-except, будет исполнен в том случае, если никаких ошибок не было вызвано:

try:
    print("Что-то произошло?")
except:
    print("Да, что-то произошло")
else:
    print("Нет, все в порядке")
Что-то произошло?
Нет, все в порядке

Блок finally

Блок finally будет исполнен не в зависимости от того, была вызвана ошибка или нет:

try:
    print(unknown)
except NameError:
    print("Переменная unknown не определена")
finally:
    print("Все ошибки обработаны!")
Переменная unknown не определена
Все ошибки обработаны!

Данный блок может быть крайне полезен, если надо обязательно выполнить какую-либо завершающую операцию, которая не была сделана в части try-except. К примеру, мы хотим записать данные в файл, который не доступен для записи:

try:
    outfile = open("test.txt", "w")
    try:
        outfile.write("Важные данные\n")
    except:
        print("Что-то пошло не так при записи в файл")
    finally:
        #   Закрываем файловый дескриптор
        outfile.close()
except:
    print("Что-то пошло не так при открытии файла")

Вызов исключения

Для вызова исключений используется ключевое слово raise. Можно вызвать исключение, если не соблюдены какие-то условия:

word = 5

if type(word) is not str:
    raise TypeError("Не строковые значения не допускаются до печати!")
else:
    print(word)
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
TypeError: Не строковые не допускаются до печати!

assert

Ключевое слово assert позволяет проверять какие-то простые условия в коде. Если эти условия не выполняются, то вызывается ошибка AssertionError. Также после запятой опционально можно указать сообщение, которые будет выведено при неверном условии:

word = 5
assert type(word) is str, "Значение переменной не является строкой"
print(word)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError: Значение переменной не является строкой