Конструкция try-except: эффективное управление ошибками в коде Python

Раздел: Ошибки -> Исключения

Обработка исключений с try except в Python

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

Базовый синтаксис try except

Самый простой способ – обернуть потенциально опасный код в блок try, а в except указать, как реагировать на любую ошибку.

try:
    number = int(input("Введите число: "))
    print(100 / number)
except:
    print("Произошла ошибка")

Try error python (ошибка try-except в python)

Если пользователь введёт не число или ноль, программа не упадёт, а выведет сообщение. Недостаток – перехватываются все исключения, включая SystemExit и KeyboardInterrupt, что не всегда желательно.

Как перехватить только определённые типы ошибок в Python?

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

try:
    value = int(input("Введите целое число: "))
except ValueError:
    print("Введено не число")

Типичная ошибка:

Перехват Exception слишком широкий. Лучше указывать конкретные типы. Если нужно несколько – перечислите их в кортеже: except (ValueError, ZeroDivisionError):.

Как получить доступ к объекту исключения и его сообщению?

Используем as e – переменная, в которую помещается экземпляр исключения.

try:
    result = 1 / 0
except ZeroDivisionError as e:
    print(f"Ошибка: {e}")

Как выполнить код, если исключение не возникло (блок else)?

Блок else выполняется, только когда в try не было ошибок. Это отделяет успешный сценарий от обработки ошибок.

try:
    number = int(input("Число: "))
except ValueError:
    print("Не число")
else:
    print(f"Вы ввели {number}")

Как гарантировать выполнение кода независимо от результата (блок finally)?

finally выполняется всегда – после try, except или else, даже если возникло исключение, не обработанное except. Используется для закрытия файлов, освобождения ресурсов.

try:
    f = open("file.txt", "r")
    data = f.read()
except FileNotFoundError:
    print("Файл не найден")
finally:
    f.close()

Распространённая проблема:

Забывают про finally при работе с файлами, что может привести к утечке дескрипторов. Всегда закрывайте ресурсы в finally или используйте менеджеры контекста with.

Как обработать несколько исключений по-разному?

Можно написать несколько блоков except для разных типов. Важен порядок – от более конкретных к общим.

try:
    x = int(input("x: "))
    y = int(input("y: "))
    result = x / y
except ValueError:
    print("Ошибка преобразования")
except ZeroDivisionError:
    print("Деление на ноль")
except Exception as e:
    print(f"Неизвестная ошибка: {e}")

Ошибки при множественных except:

Если поставить except Exception первым, он перехватит все частные случаи. Всегда располагайте конкретные исключения выше общих.

Как повторно возбудить исключение после обработки?

Используется raise без аргументов внутри блока except. Это позволяет залогировать ошибку и всё равно передать её выше.

try:
    risky_operation()
except ValueError as e:
    print("Ошибка, логируем...")
    raise

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

Наследуемся от Exception и используем в try except.

class NegativeError(Exception):
    pass

def check_positive(value):
    if value < 0:
        raise NegativeError("Число отрицательное")
    return value

try:
    check_positive(-5)
except NegativeError as e:
    print(e)

Проблема:

Перехват Exception без необходимости скрывает ошибки проектирования. Создавайте свои исключения только если это действительно улучшает читаемость кода.

Расширенные примеры работы с try except

Пример 1. Вложенные try-блоки и finally

Внутренний блок обрабатывает конкретную ошибку, внешний – более общую. Finally срабатывает даже при необработанном исключении.

Пример
def read_and_divide(filename):
    try:
        f = open(filename, 'r')
        try:
            data = f.read().strip()
            if not data:
                raise ValueError("Файл пуст")
            num = int(data)
            result = 100 / num
            print(f"Результат: {result}")
        except ValueError as e:
            print(f"Ошибка данных: {e}")
        finally:
            f.close()
            print("Файл закрыт")
    except FileNotFoundError:
        print("Файл не найден")

# Проверка
read_and_divide("numbers.txt")
# Если numbers.txt содержит "10":
# Результат: 10.0
# Файл закрыт
# Если файла нет:
# Файл не найден
# Если в файле "abc":
# Ошибка данных: invalid literal for int() with base 10: 'abc'
# Файл закрыт

Пример 2. Отлов нескольких типов исключений с разными действиями и логирование

Пример
import sys

def safe_division(a, b):
    try:
        result = a / b
    except TypeError as e:
        print(f"Тип не подходит: {e}", file=sys.stderr)
        return None
    except ZeroDivisionError:
        print("Деление на ноль", file=sys.stderr)
        return None
    else:
        return result

print(safe_division(10, 2))   # 5.0
print(safe_division(10, 0))   # None
print(safe_division("10", 2)) # None
5.0
Деление на ноль
None
Тип не подходит: unsupported operand type(s) for /: 'str' and 'int'
None

Пример 3. Создание собственного исключения с дополнительной информацией

Пример
class CustomError(Exception):
    def __init__(self, message, code):
        super().__init__(message)
        self.code = code

def process(value):
    if value < 0:
        raise CustomError("Неверное значение", code=400)
    return value * 2

try:
    process(-1)
except CustomError as e:
    print(f"Ошибка #{e.code}: {e}")
Ошибка #400: Неверное значение

Пример 4. Перехват исключения с замыканием (raise from)

Цепочка исключений помогает сохранить контекст первоначальной ошибки.

Пример
def get_data(url):
    try:
        response = requests.get(url)
        response.raise_for_status()
    except requests.ConnectionError as e:
        raise RuntimeError("Не удалось подключиться") from e

try:
    get_data("http://несуществующий.сайт.ру")
except RuntimeError as e:
    print(f"Ошибка: {e}")
    # e.__cause__ содержит исходное исключение ConnectionError
Ошибка: Не удалось подключиться

Пример 5. Использование try except для выхода из глубокой рекурсии

Пример
def factorial(n):
    if n < 0:
        raise ValueError("Факториал отрицательного числа не определён")
    if n == 0:
        return 1
    # Намеренная ошибка для демонстрации
    if n > 900:
        raise RecursionError("Слишком глубокий вызов")
    return n * factorial(n-1)

try:
    print(factorial(10))
except (ValueError, RecursionError) as e:
    print(f"Ошибка расчёта: {e}")
3628800

Ошибка try-except в Python - comments

En
Try error python (python)