Блоки try и except: как писать надёжный код
Основы обработки исключений
Наиболее эффективный способ обработки исключений в Python - использование конструкции try-except. Она позволяет перехватывать ошибки во время выполнения программы и реагировать на них без аварийного завершения.
Базовый синтаксис:
try:
risky_code()
except SomeException:
handle_error()Python создать ошибку (создание исключений в python)
Пример с делением на ноль:
try:
result = 10 / 0
except ZeroDivisionError:
print("Деление на ноль запрещено")класс ошибок python (классы исключений в python)
Деление на ноль запрещено
Python except (обработка исключений в python с помощью try-except)
Как отловить только определённый тип исключения?
Указывается конкретный класс исключения после except.
try:
value = int("abc")
except ValueError:
print("Не удалось преобразовать строку в число")Не удалось преобразовать строку в число
Если исключение другого типа, оно не будет перехвачено и программа завершится с ошибкой.
Как обработать разные исключения по-разному?
Используется несколько блоков except:
try:
x = int(input("Введите число: "))
result = 100 / x
except ValueError:
print("Введите корректное число")
except ZeroDivisionError:
print("Нельзя делить на ноль")
except Exception as e:
print(f"Неизвестная ошибка: {e}")Порядок блоков важен: сначала идут более специфичные исключения, затем общие.
Как выполнить код, если ошибка не произошла?
Блок else выполняется, только если try завершился без исключения.
try:
number = int("42")
except ValueError:
print("Некорректное число")
else:
print(f"Число успешно получено: {number}")Число успешно получено: 42
Как гарантировать выполнение кода независимо от ошибки?
Блок finally выполняется всегда, даже если в try или except был return или выброшено новое исключение.
try:
f = open("file.txt", "r")
content = f.read()
except FileNotFoundError:
print("Файл не найден")
finally:
print("Закрытие файла (если открыт)")
if 'f' in locals():
f.close()Файл не найден Закрытие файла (если открыт)
Как перехватить любое исключение?
Можно использовать except без указания типа или с Exception. Однако это считается плохой практикой, так как скрывает неожиданные ошибки.
try:
risky_operation()
except:
print("Что-то пошло не так")Лучше записывать информацию об исключении:
try:
risky_operation()
except Exception as e:
print(f"Ошибка: {e}")Как повторно возбудить исключение после обработки?
Используется ключевое слово raise без аргументов внутри блока except.
try:
value = int("abc")
except ValueError:
print("Была ошибка преобразования")
raise # повторно возбуждает перехваченное исключениеТакже можно изменить исключение, создав новое с помощью raise ... from.
Расширенные примеры работы с исключениями
Создание собственного исключения
class ValidationError(Exception):
"""Исключение для ошибок валидации данных."""
pass
def validate_age(age):
if age < 0 or age > 150:
raise ValidationError("Некорректный возраст")
try:
validate_age(200)
except ValidationError as e:
print(f"Ошибка валидации: {e}")Ошибка валидации: Некорректный возраст
Цепочка исключений (raise from)
try:
int("abc")
except ValueError as orig_error:
raise RuntimeError("Не удалось преобразовать строку") from orig_errorВывод (если не перехватить):
Traceback (most recent call last): ... ValueError: invalid literal for int() with base 10: 'abc' The above exception was the direct cause of the following exception: RuntimeError: Не удалось преобразовать строку
Игнорирование исключений с contextlib.suppress
from contextlib import suppress
import os
with suppress(FileNotFoundError):
os.remove("temp.txt") # не возникнет ошибки, если файла нетВложенные try-except
def safe_divide(a, b):
try:
try:
return a / b
except ZeroDivisionError:
print("Внутренняя обработка: деление на ноль")
return None
except Exception as e:
print(f"Внешняя обработка: {e}")
return NoneОбработка ошибок при работе с сетью
import requests
try:
response = requests.get("https://nonexistent-domain.xyz", timeout=5)
response.raise_for_status()
except requests.exceptions.ConnectionError:
print("Не удалось подключиться к серверу")
except requests.exceptions.Timeout:
print("Превышено время ожидания")
except requests.exceptions.HTTPError as e:
print(f"HTTP ошибка: {e.response.status_code}")Логирование traceback
import logging
import traceback
logging.basicConfig(level=logging.ERROR)
try:
1 / 0
except ZeroDivisionError:
logging.error("Произошла ошибка:\n%s", traceback.format_exc())ERROR:root:Произошла ошибка: Traceback (most recent call last): File "<string>", line 1, in <module> ZeroDivisionError: division by zero