- Узнавать самые частые исключения
- Перехватывать ошибку через
tryиexceptи продолжать работу программы - Использовать
else,finallyиraise
Ты написал калькулятор. Пользователь вводит «двенадцать» вместо числа или делит на ноль — и программа останавливается с красным сообщением об ошибке. Такие программы никто не любит! Хорошая программа готова к ошибкам: она распознаёт проблему, понятно объясняет её пользователю и продолжает работу.
Что такое исключения?
Ошибки бывают двух видов. Синтаксические ошибки (SyntaxError) — это ошибки в записи кода, и программа даже не запускается. Если код написан правильно, но при выполнении что-то идёт не так, Python создаёт исключение (exception). Если исключение не перехвачено, программа останавливается, и Python показывает «traceback» — отчёт об ошибке:
Traceback (most recent call last):
File "main.py", line 2, in <module>
print(10 / count)
ZeroDivisionError: division by zero| Исключение | Когда возникает | Пример |
|---|---|---|
ValueError | тип подходит, но само значение нет | int('abc') |
TypeError | операция невозможна для этого типа | '5' + 5 |
ZeroDivisionError | деление на ноль | 10 / 0 |
IndexError | такого индекса нет | [1, 2][5] |
KeyError | в словаре нет такого ключа | {}['a'] |
NameError | переменной с таким именем нет | print(scor) |
try и except
Код, который может вызвать ошибку, помещаем в блок try. Если возникает исключение, Python пропускает остаток блока try и переходит к подходящему блоку except. После этого программа продолжает работу как обычно.
text = 'abc'
try:
number = int(text)
print('Number:', number)
except ValueError:
print('That is not a number!')
print('The program continues.')▸ Ожидаемый результат
That is not a number! The program continues.
text значение '25' и сравни результат.У одного try может быть несколько блоков except — каждый перехватывает свой тип исключения. Запись except ... as e сохраняет само исключение в переменной e; если её вывести, увидишь пояснение Python.
def safe_divide(a, b):
try:
return a / b
except ZeroDivisionError:
print('Cannot divide by zero!')
except TypeError as e:
print('Wrong type:', e)
return None
print(safe_divide(10, 2))
print(safe_divide(5, 0))
print(safe_divide(5, 'x'))▸ Ожидаемый результат
5.0 Cannot divide by zero! None Wrong type: unsupported operand type(s) for /: 'int' and 'str' None
else и finally
- Блок
elseвыполняется, только еслиtryзавершился без ошибки, — туда пиши работу с успешным результатом. - Блок
finallyвыполняется всегда — была ошибка или нет. Обычно в нём завершают работу: закрывают файл, выводят сообщение.
for value in ['42', 'seven']:
try:
n = int(value)
except ValueError:
print(f'{value}: not a number')
else:
print(f'{value}: doubled is {n * 2}')
finally:
print('checked', value)▸ Ожидаемый результат
42: doubled is 84 checked 42 seven: not a number checked seven
raise: вызов собственного исключения
Иногда для Python всё в порядке, а для твоей программы — нет: например, возраст не может быть отрицательным. В таких случаях исключение можно вызвать самому с помощью raise. Код ниже имитирует ответы пользователя и принимает первый правильный возраст:
answers = ['abc', '-3', '14']
for answer in answers:
try:
age = int(answer)
if age <= 0:
raise ValueError('age must be positive')
except ValueError as e:
print(f'Bad input {answer}: {e}')
else:
print('Accepted age:', age)
break▸ Ожидаемый результат
Bad input abc: invalid literal for int() with base 10: 'abc' Bad input -3: age must be positive Accepted age: 14
Преобразуй строки из списка data в числа с помощью int() и сложи их. На элементе, который нельзя преобразовать, программа не должна останавливаться: перехвати ошибку через try/except ValueError и выведи Skipped: и этот элемент. В конце выведи Total: и сумму.
data = ['12', 'seven', '30', '4.5', '8']
total = 0
# for each item: try to add int(item) to total,
# on ValueError print Skipped: and the item
# print Total: and total▸ Ожидаемый результат
Skipped: seven Skipped: 4.5 Total: 50
На складе 100 тетрадей. Напиши функцию sell(stock, count): если count равен нулю или отрицателен, она вызывает ValueError('count must be positive'), если он больше остатка — ValueError('not enough in stock'), а иначе возвращает, сколько осталось. Цикл в заготовке проверяет каждую продажу через try/except — не меняй его.
# define sell(stock, count) here
stock = 100
for count in [30, -5, 90, 50]:
try:
stock = sell(stock, count)
print('Sold', count, '- left:', stock)
except ValueError as e:
print('Error:', e)▸ Ожидаемый результат
Sold 30 - left: 70 Error: count must be positive Error: not enough in stock Sold 50 - left: 20
Главное
- Исключение — ошибка во время выполнения; если его не перехватить, программа остановится.
tryсодержит рискованный код, аexceptперехватывает конкретное исключение.elseвыполняется, только если ошибки не было, аfinally— всегда.- Собственное исключение вызывают через
raise:raise ValueError('...'). - Последняя строка traceback показывает тип исключения и его причину.
Проверь себя
Вопросов: 10. Каждый правильный ответ приносит XP.
int('hello')?