> For the complete documentation index, see [llms.txt](https://pavel-karateev.gitbook.io/intermediate-python/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://pavel-karateev.gitbook.io/intermediate-python/sintaksis/exceptions.md).

# Исключения

Работа с исключениям это отдельное искусство, освоив которое вы получите инструмент огромного потенциала. Я продемонстрирую несколько методов работы с исключениями в этой главе.

В конечном итоге, нас интересует синтаксис `try/except`. Код, который может вызвать исключение, помещается в `try` блок, обработка исключения - в `except`. Простой пример:

```python
try:
    file = open('test.txt', 'rb')
except IOError as e:
    print('Было вызвано исключение IOError. {}'.format(e.args[-1]))
```

В примере выше мы перехватываем только исключение `IOError`. Многие новички не знают, что мы можем обрабатывать несколько исключений.

## Обработка множества исключений

Мы можем использовать три метода обработки множества исключений. Первый заключается в создании кортежа из всех возможных исключений. Что-то подобное:

```python
try:
    file = open('test.txt', 'rb')
except (IOError, EOFError) as e:
    print("Было вызвано исключение. {}".format(e.args[-1]))
```

Другой методы заключается в обработке каждого исключения в отдельном блоке `except`. Мы можем иметь неограниченное их число (но не менее одного). Очередной пример:

```python
try:
    file = open('test.txt', 'rb')
except EOFError as e:
    print("Было вызвано исключение EOFError.")
    raise e
except IOError as e:
    print("Было вызвано исключение IOError.")
    raise e
```

Таким образом, если исключение не перехватывается первым блоком `except`, то оно может быть обработано следующим, или не быть обработанным вовсе. Последний метод заключается в перехвате ВСЕХ исключений:

```python
try:
    file = open('test.txt', 'rb')
except Exception:
    # Логирование, если оно вам требуется
    raise
```

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

## `finally`

Основной код помещается в блок `try`. Дальше идут блоки `except`, которые исполняются, если в блоке `try` было вызвано определённое исключение. Третьим типом блоков, следующим за двумя первыми, может быть `finally`. Код в блоке `finally` будет исполнен вне зависимости от того, вызвал ли код в блоке `try` исключение или нет. Это может быть полезно для финальной "чистки" после работы основного скрипта. Вот простой пример:

```python
try:
    file = open('test.txt', 'rb')
except IOError as e:
    print('Было вызвано исключение IOError. {}'.format(e.args[-1]))
finally:
    print("Я буду напечатан вне зависимости от исключений в блоке try!")

# Вывод: Было вызвано исключение IOError. No such file or directory
#        Я буду напечатан вне зависимости от исключений в блоке try!
```

## `try/else`

Иногда мы можем захотеть исполнить определенный код, если исключения **не было**. Это легко сделать с помощью блока `else`. Вы можете спросить: почему нам нужен `else`, если мы можем поместить этот код в блок `try`? Проблема в том, что исключение в этом коде, может быть в свою очередь поймано `try`, а мы можем этого и не хотеть. В целом, `else` нечасто используется, и я, честно говоря, редко к нему прибегаю сам. Пример:

```python
try:
    print('Я уверен, исключений не будет!')
except Exception:
    print('Исключение')
else:
    # Любой код, который должен быть исполнен, если исключение в блоке
    # try не было вызвано, но для которого не должна проводиться
    # обработка исключений
    print('Я буду исполнен, если в try не будет исключений.'
          'Мои исключения не будут обрабатываться.')
finally:
    print('Я буду исполнен в любом случае!')

# Вывод: Я уверен, исключений не будет!
#        Я буду исполнен, если в try не будет исключений. Мои исключения не будут обрабатываться.
#        Я буду исполнен в любом случае!
```

Блок `else`, таким образом, исполняется при отсутствии исключений в блоке `try`. `else` исполняется перед `finally`.
