Блоки else и finally
Блоки else и finally в try/except Python: код при успехе, гарантированная очистка ресурсов и полная структура обработки ошибок.
Блок
try/exceptможно расширить двумя необязательными секциями:else(выполняется, если ошибок не было) иfinally(выполняется всегда — при успехе и при ошибке).
Полная структура
try:
# рискованный код
pass
except ТипОшибки:
# если произошла ошибка
pass
else:
# если ошибок НЕ было
pass
finally:
# выполняется в любом случае
pass
else — код при успехе
def parse_number(s):
try:
n = int(s)
except ValueError:
print(f'"{s}" — не число')
else:
# этот блок выполняется только если int(s) не выбросил ошибку
print(f'Успешно: {n} * 2 = {n * 2}')
parse_number("10")
parse_number("привет")
Вывод:
Успешно: 10 * 2 = 20 "привет" — не число
Зачем нужен
else, если можно просто написать код послеtry? Потому что код вelseне перехватывается текущимexcept— если в нём возникнет ошибка, она не будет ошибочно поглощена.
finally — обязательная очистка
def read_config(path):
f = None
try:
f = open(path, "r", encoding="utf-8")
return f.read()
except FileNotFoundError:
print(f"Файл {path!r} не найден")
return ""
finally:
if f:
f.close()
print("Файл закрыт") # выполнится в любом случае
result = read_config("config.txt")
print("Результат:", repr(result))
Вывод:
Файл 'config.txt' не найден Результат: ''
finally выполнится даже если функция вернёт значение через return или выбросит исключение. Это идеальное место для освобождения ресурсов: закрытия файлов, соединений с БД и т.д.
Все четыре блока вместе
values = [10, 20, 0, 5]
for v in values:
try:
result = 100 / v
except ZeroDivisionError:
print(f"{v}: ошибка деления")
else:
print(f"{v}: результат = {result:.1f}")
finally:
print(f" (обработан элемент {v})")
Вывод:
10: результат = 10.0 (обработан элемент 10) 20: результат = 5.0 (обработан элемент 20) 0: ошибка деления (обработан элемент 0) 5: результат = 20.0 (обработан элемент 5)
Коротко
elseвыполняется, только если вtryне возникло исключений — удобен для кода, который зависит от успеха.finallyвыполняется всегда — при успехе, ошибке,returnи даже при необработанном исключении.- Используйте
finallyдля освобождения ресурсов (файлы, соединения, блокировки). - На практике
withзаменяет большинство паттернов сfinallyдля файлов.
Проверьте себя
1. Когда выполняется блок else в конструкции try/except/else?
AВсегда после try
BТолько если исключение было поймано
CТолько если в блоке try не возникло исключений
DТолько если блок finally завершился успешно
2. Когда выполняется блок finally?
AТолько при успехе
BТолько при ошибке
CВсегда — при успехе, ошибке, return и необработанном исключении
DТолько если нет блока except
3. Для чего в первую очередь используют блок finally?
AДля повторного выброса исключения
BДля логирования ошибок
CДля освобождения ресурсов (закрытие файлов, соединений)
DДля возврата значения функции