Привет! Мы уже научились обрабатывать ошибки с помощью try-except и выполнять код при успехе через else. Но что, если нужно выполнить код в любом случае — была ошибка или нет?
Именно для этого существует блок finally.
В этой статье мы разберём:
- Что такое
finally - Когда он выполняется
- Зачем нужен
finally - Примеры использования
- Что нужно знать перед началом
- Основная часть
- Что такое finally
- finally при ошибке
- finally без except
- finally vs else
- Зачем нужен finally
- Пример с файлом
- Пример с БД
- finally с возвратом значения
- finally без try
- Примеры из реальной жизни
- Задачи для закрепления
- Нюансы и подводные камни
- finally может переопределить return
- finally не должен содержать ошибок
- finally без except
- Частые ошибки и как их избежать
- Ошибка 1: finally без try
- Ошибка 2: Ошибка в finally
- Ошибка 3: finally не должен содержать return
- Шпаргалка
- Заключение / Выводы
- КВИЗ
- Что дальше?
Что нужно знать перед началом
Для этого урока тебе понадобится:
- Установленный Python
- Базовое понимание
try-except(статьи 1–4 в этом подменю)
Совет:
finally— это гарантия, что важные действия (закрытие файлов, освобождение ресурсов) будут выполнены.
Основная часть
Что такое finally
finally — это блок, который выполняется всегда, независимо от того, возникла ошибка или нет.
try:
print("Начало")
result = 10 / 2
print("Успешно")
except ZeroDivisionError:
print("Ошибка")
finally:
print("Это выполнится всегда")Результат:
Начало
Успешно
Это выполнится всегдаfinally при ошибке
try:
print("Начало")
result = 10 / 0
print("Успешно")
except ZeroDivisionError:
print("Ошибка")
finally:
print("Это выполнится всегда")Результат:
Начало
Ошибка
Это выполнится всегдаfinally без except
finally можно использовать и без except.
try:
file = open("data.txt", "r")
content = file.read()
except FileNotFoundError:
print("Файл не найден")
finally:
# Закрываем файл, даже если он не открылся
print("Завершение работы")finally vs else
| Блок | Когда выполняется |
|---|---|
else | Только если ошибки НЕ было |
finally | Всегда |
try:
result = 10 / 2
except ZeroDivisionError:
print("Ошибка")
else:
print("Успешно")
finally:
print("Это всегда")Зачем нужен finally
finally используется для:
- Закрытия файлов
- Освобождения сетевых соединений
- Закрытия подключений к БД
- Логирования
- Очистки ресурсов
def read_file_safe(filename):
file = None
try:
file = open(filename, "r")
return file.read()
except FileNotFoundError:
return "Файл не найден"
finally:
if file:
file.close()
print("Файл закрыт")Пример с файлом
def process_file(filename):
try:
with open(filename, "r") as file:
data = file.read()
return data
except FileNotFoundError:
print("Файл не найден")
return None
finally:
print("Обработка файла завершена")Пример с БД
def get_user_from_db(user_id):
connection = None
try:
connection = connect_to_db()
cursor = connection.cursor()
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
return cursor.fetchone()
except ConnectionError:
print("Ошибка подключения")
return None
finally:
if connection:
connection.close()
print("Соединение закрыто")finally с возвратом значения
Если в try или except есть return, finally всё равно выполнится.
def safe_divide(a, b):
try:
return a / b
except ZeroDivisionError:
return None
finally:
print("Деление выполнено")Важно:
finallyвыполняется до возврата значения.
finally без try
finally не может существовать без try.
# Ошибка!
finally:
print("Что-то")Примеры из реальной жизни
Пример 1. Закрытие файла:
def read_config(filename):
try:
with open(filename, "r") as file:
return file.read()
except FileNotFoundError:
print("Файл не найден")
return None
finally:
print("Файл обработан")Пример 2. Логирование:
def process_data(data):
try:
result = complex_operation(data)
return result
except ValueError:
print("Ошибка в данных")
return None
finally:
print(f"Обработка данных завершена: {data}")Задачи для закрепления
Задача 1. Напиши программу, которая открывает файл и в любом случае выводит «Операция завершена».
Задача 2. Напиши функцию, которая делит два числа и в любом случае выводит «Деление выполнено».
Задача 3. В чём разница между else и finally?
Задача 4. Напиши функцию, которая подключается к БД и в любом случае закрывает соединение.
Задача 5. Будет ли выполнен finally, если в try произойдёт ошибка?
Ответы:
Задача 1.
try:
with open("file.txt", "r") as file:
content = file.read()
except FileNotFoundError:
print("Файл не найден")
finally:
print("Операция завершена")Задача 2.
def safe_divide(a, b):
try:
return a / b
except ZeroDivisionError:
return None
finally:
print("Деление выполнено")Задача 3.
# else — выполняется при успехе
# finally — выполняется всегдаЗадача 4.
def get_user(user_id):
connection = None
try:
connection = connect_to_db()
return connection.query(f"SELECT * FROM users WHERE id={user_id}")
except ConnectionError:
return None
finally:
if connection:
connection.close()Задача 5.
# Да, finally выполняется всегда, даже при ошибкеНюансы и подводные камни
finally может переопределить return
def test():
try:
return 1
finally:
return 2
print(test()) # 2 (finally переопределил return)Важно: Если
finallyсодержитreturn, он переопределяет значение изtryилиexcept.
finally не должен содержать ошибок
Если в finally возникает ошибка, она не будет обработана (если только не обёрнута в другой try).
try:
result = 10 / 2
except ZeroDivisionError:
print("Ошибка")
finally:
result = 1 / 0 # Ошибка! Не перехватываетсяfinally без except
try:
result = 10 / 2
finally:
print("Завершено")
# Если ошибка — она не будет перехвачена, но finally выполнитсяЧастые ошибки и как их избежать
Ошибка 1: finally без try
finally: # Ошибка!
print("Что-то")Ошибка 2: Ошибка в finally
try:
result = 10 / 2
finally:
print(1 / 0) # Ошибка не обрабатываетсяОшибка 3: finally не должен содержать return
def test():
try:
return 1
finally:
return 2 # Переопределяет return из tryШпаргалка
| Что нужно | Как пишется |
|---|---|
| Блок всегда | finally: |
| finally без except | try: ... finally: ... |
| finally после except | try: ... except: ... finally: ... |
| finally с else | try: ... except: ... else: ... finally: ... |
Заключение / Выводы
Сегодня мы узнали:
finally— выполняется всегда- Используется для освобождения ресурсов
- Отличие
finallyотelse finallyможет переопределитьreturn






