08. Исключения и отладка

Что такое исключения

Исключение — это ошибка, которая возникает во время выполнения программы. Если её не обработать, программа завершится аварийно.
Ошибка — это не враг, а сигнал, что программе нужно объяснить, что делать в необычной ситуации.

Пример:


print(10 / 0)
Результат:

ZeroDivisionError: division by zero

Зачем нужны try и except

Чтобы программа не ломалась, ошибки можно перехватывать и обрабатывать:

try:
    number = int(input('Введите число: '))
    print('Результат:', 10 / number)
except ZeroDivisionError:
    print('Нельзя делить на ноль!')
except ValueError:
    print('Введите, пожалуйста, число!')

Теперь программа не упадёт, если пользователь введёт неправильное значение.

Блок finally

Блок finally выполняется всегда — даже если произошла ошибка.

try:
    f = open('data.txt', 'r', encoding='utf-8')
    print(f.read())
except FileNotFoundError:
    print('Файл не найден!')
finally:
    print('Попытка чтения завершена.')
Результат:

Файл не найден!
Попытка чтения завершена.

Использование else

Блок else выполняется, если ошибок не было:

try:
    n = int(input('Введите число: '))
except ValueError:
    print('Ошибка: нужно ввести число!')
else:
    print('Всё отлично, число:', n)

Обработка нескольких исключений сразу

Иногда удобно перехватывать сразу несколько типов ошибок:

try:
    x = int(input('Введите число: '))
    y = 10 / x
except (ZeroDivisionError, ValueError):
    print('Ошибка: некорректный ввод!')

Общее исключение Exception

Если не знаешь, какая именно ошибка может произойти, можно поймать все сразу:

try:
    something = 10 / 0
except Exception as e:
    print('Произошла ошибка:', e)

Создание своих исключений

Можно создавать собственные ошибки с помощью raise:

def divide(a, b):
    if b == 0:
        raise ValueError('На ноль делить нельзя!')
    return a / b

try: print(divide(10, 0)) except ValueError as e: print('Ошибка:', e)

Отладка программ

Отладка (debugging) — это поиск и исправление ошибок в коде.

1. Используй print() для проверки значений


def calculate(a, b):
    print('a =', a, 'b =', b)
    return a + b

print(calculate(3, '5'))

Результат:

TypeError: unsupported operand type(s) for +: 'int' and 'str'
Ошибка подсказывает, что нужно привести тип:

return a + int(b)

2. Используй отладчик (breakpoints)

Если вы работаете в Visual Studio Code или PyCharm, можно ставить точки остановки (breakpoints), чтобы пошагово проверить работу программы.

3. Используй assert

assert проверяет, что условие истинно, иначе вызывает ошибку:

number = -5
assert number > 0, 'Число должно быть положительным!'
Результат:

AssertionError: Число должно быть положительным!

Практические примеры

  • Попроси пользователя ввести два числа и дели одно на другое с обработкой ошибок.
  • Создай функцию, которая открывает файл и возвращает текст, если файл существует, или сообщение об ошибке.
  • Напиши функцию, которая проверяет возраст пользователя и вызывает ValueError, если введено отрицательное число.

Типичные ошибки новичков

  • Забывают указывать тип ошибки (ловят всё подряд без причины).
  • Скрывают ошибки пустым except (и потом не понимают, что пошло не так).
  • Не закрывают файлы, если не используют with open().
  • Не читают текст ошибки, хотя он помогает найти проблему.

Мини-проект: Калькулятор с защитой от ошибок


while True:
    try:
        a = float(input('Введите первое число: '))
        b = float(input('Введите второе число: '))
        result = a / b
    except ValueError:
        print('Ошибка: нужно вводить числа!')
        continue
    except ZeroDivisionError:
        print('Ошибка: деление на ноль!')
        continue
    else:
        print('Результат:', result)
        break
    finally:
        print('Попробуем снова...')

Итоги урока

Теперь вы знаете:
  • Как обрабатывать ошибки с помощью try, except, else и finally.
  • Как создавать собственные исключения с raise.
  • Как искать ошибки через print, assert и отладчик.
  • Как писать безопасный и устойчивый код.