Несколько except и else / finally

Несколько except и else / finally

В предыдущем уроке мы познакомились с базовым try/except. Python предлагает расширенный синтаксис для более тонкой обработки: блок else (выполняется когда исключений не было) и finally (выполняется всегда). Вместе они образуют полную конструкцию обработки ошибок.

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

try:
    # потенциально опасный код
    pass
except ValueError:
    # если произошёл ValueError
    pass
except (KeyError, IndexError) as e:
    # если произошёл KeyError или IndexError
    pass
else:
    # если try завершился БЕЗ исключений
    pass
finally:
    # выполняется ВСЕГДА: и при успехе, и при исключении
    pass

Каждый блок необязателен, кроме одного except (или finally). Порядок строго такой: tryexcept*elsefinally.

Блок else: код успешного пути

else выполняется, только если в try не возникло исключений. Это позволяет чётко отделить «опасный код» от «кода при успехе»:

def load_config(filename):
    try:
        with open(filename, "r", encoding="utf-8") as f:
            data = f.read()
    except FileNotFoundError:
        print(f"Файл {filename} не найден, используем настройки по умолчанию")
        return {}
    else:
        # сюда попадаем только если файл открылся успешно
        import json
        return json.loads(data)

config = load_config("settings.json")

Без else пришлось бы вложить json.loads(data) в блок try, рискуя перехватить json.JSONDecodeError там, где мы его не ожидали.

Блок finally: код очистки

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

def process_file(filename):
    f = None
    try:
        f = open(filename, "r", encoding="utf-8")
        return f.read()
    except FileNotFoundError:
        return ""
    finally:
        if f is not None:
            f.close()   # закроем файл в любом случае
            print("Файл закрыт")

На практике для файлов лучше использовать with open(...) — он делает то же самое через контекстный менеджер. Но finally незаменим для других ресурсов: соединений с базой, блокировок, временных файлов.

finally выполняется даже при return

Это важная тонкость: finally выполняется даже если в try или except встречается return:

def demo():
    try:
        return "из try"
    finally:
        print("finally всё равно выполнился")

result = demo()
# finally всё равно выполнился
print(result)   # из try

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

Если определено несколько except, Python проверяет их сверху вниз и использует первый подходящий. Поэтому более конкретные исключения ставят выше:

try:
    result = int(input("Число: "))
    print(100 / result)
except ValueError:
    print("Это не число")
except ZeroDivisionError:
    print("Ноль недопустим")
except Exception as e:
    print(f"Неожиданная ошибка: {e}")

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

Практический пример: чтение и парсинг JSON

import json

def read_json(filename):
    try:
        with open(filename, "r", encoding="utf-8") as f:
            text = f.read()
    except FileNotFoundError:
        return None, "Файл не найден"
    except PermissionError:
        return None, "Нет прав на чтение"
    else:
        try:
            data = json.loads(text)
        except json.JSONDecodeError as e:
            return None, f"Невалидный JSON: {e}"
        else:
            return data, None
    finally:
        print("Чтение завершено")

data, error = read_json("config.json")
if error:
    print(f"Ошибка: {error}")

Итог

  • else — выполняется если try завершился без исключений; отделяет «опасный» код от «успешного».
  • finally — выполняется всегда (успех или исключение); используется для очистки ресурсов.
  • Несколько except проверяются сверху вниз; конкретные — выше, общие — ниже.
  • finally выполняется даже при return внутри try.

В следующем уроке разберём raise — как самостоятельно генерировать исключения в собственном коде.

Попробуйте интерактивную версию

Практические задачи, квизы и AI-наставник — бесплатный старт без карты

Перейти к практике