try...except
с последовательными блоками except
, располагая их в порядке от наиболее специфичного к наиболее общему исключению. Это позволяет обработать конкретные типы исключений, а более общие будут обработаны в соответствующих блоках except
. Например:
try:
# Код, который может вызвать исключение
raise SpecificException()
except SpecificException as e:
# Обработка специфичного исключения
print(f"Специфичное исключение: {e}")
except GeneralException as e:
# Обработка более общего исключения (родительского класса SpecificException)
print(f"Общее исключение: {e}")
except Exception as e:
# Обработка всех остальных исключений
print(f"Неизвестное исключение: {e}")
Где SpecificException
наследуется от GeneralException
(или другого базового класса). Важно помнить, что except Exception
следует размещать в самом конце, чтобы не перехватить специфичные исключения раньше времени.
Обработка нескольких собственных исключений с иерархией классов включает в себя создание базового класса исключения, от которого наследуются более специфичные исключения. При обработке необходимо учитывать порядок блоков except
, чтобы не перехватить исключение более общим обработчиком, чем требуется.
Пример:
class CustomError(Exception):
"""Базовый класс для всех кастомных исключений"""
pass
class ValidationError(CustomError):
"""Исключение для ошибок валидации данных"""
pass
class InvalidEmailError(ValidationError):
"""Исключение для невалидного формата email"""
pass
class DatabaseError(CustomError):
"""Исключение для ошибок работы с базой данных"""
pass
class ConnectionError(DatabaseError):
"""Исключение для ошибок соединения с базой данных"""
pass
def process_data(email):
try:
if "@" not in email:
raise InvalidEmailError("Некорректный формат email")
# ... другая логика ...
except InvalidEmailError as e:
print(f"Ошибка валидации email: {e}")
# Обработка конкретной ошибки валидации email
except ValidationError as e:
print(f"Общая ошибка валидации: {e}")
# Обработка всех ошибок валидации (включая InvalidEmailError)
except CustomError as e:
print(f"Общая ошибка: {e}")
# Обработка всех кастомных ошибок (включая ValidationError и InvalidEmailError)
except Exception as e:
print(f"Непредвиденная ошибка: {e}")
# Обработка всех остальных исключений
else:
print("Данные обработаны успешно")
finally:
print("Блок finally: выполняется всегда")
# Пример использования
process_data("invalid-email")
process_data("valid@email.com")
Ключевые моменты:
except
должны быть упорядочены от более специфичных к более общим. Если сначала указать except CustomError
, то except InvalidEmailError
никогда не будет выполнен, так как InvalidEmailError
является подклассом CustomError
.CustomError
) для обработки целой группы связанных ошибок.else
блок: Блок else
выполняется, если в блоке try
не возникло ни одного исключения. Это хорошее место для кода, который должен выполняться только при успешном выполнении.finally
блок: Блок finally
выполняется всегда, независимо от того, было ли выброшено исключение или нет. Он полезен для освобождения ресурсов (например, закрытия файлов или соединений с базой данных).Exception
или его подклассов.Альтернативный подход (более лаконичный, при необходимости выполнять одинаковые действия для нескольких исключений):
try:
# ... код, который может вызвать исключение ...
except (InvalidEmailError, ConnectionError) as e:
print(f"Ошибка при работе с данными: {e}")
# Обработка InvalidEmailError или ConnectionError
except CustomError as e:
print(f"Общая кастомная ошибка: {e}")
В этом случае, если возникнет либо InvalidEmailError
, либо ConnectionError
, будет выполнен один и тот же блок кода.