JavaRush /Курси /Модуль 1: Python Core /Створення власного виключення

Створення власного виключення

Модуль 1: Python Core
Рівень 10 , Лекція 6
Відкрита

7.1 Створення користувацьких виключень

Іноді стандартні виключення Python не повністю задовольняють потреби твого застосунку. В таких випадках ти можеш створювати свої власні виключення, успадкувавши їх від базового класу Exception або будь-якого іншого підходящого класу виключень.

Основи створення користувацьких виключень

Створення користувацького виключення включає в себе визначення нового класу, який наслідується від базового класу Exception. Ти можеш додати власні методи і атрибути в твій клас виключення для надання додаткової інформації про помилку.

Приклад створення простого користувацького виключення

Крок 1: Визначення користувацького виключення


class MyCustomError(Exception):
    """Клас для користувацького виключення."""
    pass
        

Крок 2: Використання користувацького виключення


def check_value(value):
    if value < 0:
        raise MyCustomError("Значення не повинно бути менше нуля")
            
try:
    check_value(-1)
except MyCustomError as e:
    print(f"Сталося користувацьке виключення: {e}")
            

Все дуже просто. Головне, щоб твоє виключення було успадковане від класу Exception або одного з його нащадків.

7.2 Створення виключення з додатковими атрибутами

Ти можеш додавати атрибути і методи в твій клас виключення для передачі додаткової інформації про виниклу помилку.

Приклад:


class NegativeValueError( Exception ):
    """Клас для користувацького виключення при від'ємному значенні."""
    def __init__(self, value, message = "Значення не повинно бути менше нуля"):
        self.value = value
        self.message = message
        super().__init__(self.message)

    def __str__(self):
        return f'{self.message}: {self.value}'

Використання виключення з додатковими атрибутами


def check_value(value):
    if value < 0:
        raise NegativeValueError(value)

try:
    check_value(-1)
except NegativeValueError as e:
    print(f"Сталося користувацьке виключення: {e}")

Наше виключення — це клас, який успадкований від класу Exception. Тому з ним можна робити все те ж, що й з будь-яким іншим класом: додавати поля, методи, параметри конструктора і т.п.

Все для твого зручності, і зручності тих програмістів, які будуть перехоплювати твої виключення.

7.3 Створення ієрархії користувацьких виключень

Для більш складних застосунків корисно створювати ієрархії користувацьких виключень. Це дозволяє групувати пов'язані виключення і спрощує їх обробку.

Приклад:


class ApplicationError(Exception):
    """Базовий клас для всіх виключень застосунку."""
    pass

class NegativeValueError(ApplicationError):
    """Клас для користувацького виключення при від'ємному значенні."""
    def __init__(self, value, message="Значення не повинно бути менше нуля"):
        self.value = value
        self.message = message
        super().__init__(self.message)

    def __str__(self):
        return f'{self.message}: {self.value}'

class ValueTooLargeError(ApplicationError):
    """Клас для користувацького виключення при занадто великому значенні."""
    def __init__(self, value, message="Значення занадто велике"):
        self.value = value
        self.message = message
        super().__init__(self.message)

    def __str__(self):
        return f'{self.message}: {self.value}'

Використання ієрархії користувацьких виключень


def check_value(value):
    if value < 0:
        raise NegativeValueError(value)
    elif value > 100:
        raise ValueTooLargeError(value)

try:
    check_value(150)
except NegativeValueError as e:
    print(f"Сталося виключення: {e}")
except ValueTooLargeError as e:
    print(f"Сталося виключення: {e}")
except ApplicationError as e:
    print(f"Загальне виключення застосунку: {e}")

7.4 Порядок перехоплення виключень

При перехопленні виключень, особливо з однієї ієрархії, важливо вказувати їх правильний порядок. І хоча код всередині блоків except ніколи не виконується одночасно, вся справа в тому, що базовий клас виключення здатний захоплювати виключення всіх класів-нащадків.

Наприклад, код:


def check_value(value):
    if value < 0:
        raise NegativeValueError(value)
    elif value > 100:
        raise ValueTooLargeError(value)
    
try:
    check_value(150)
except ApplicationError as e: # захопить виключення типу ApplicationError і всіх його нащадків
    print(f"Загальне виключення застосунку: {e}")

У блоці except будуть перехоплені виключення типу ApplicationError і всіх його класів-нащадків.

А оскільки всі виключення є нащадками класу Exception, то такий код захопить взагалі всі виключення:


def check_value(value):
    if value < 0:
        raise NegativeValueError(value)
    elif value > 100:
        raise ValueTooLargeError(value)
    
try:
    check_value(150)
except Exception as e:
    print(f"Захоплення всіх виключень: {e}")
except ApplicationError as e: # Цей код ніколи не виконається
    print(f"Загальне виключення застосунку: {e}")

Захоплення виключень у блоці except ApplicationError ніколи не станеться, тому що блок except Exception захопить взагалі всі виключення типу Exception і будь-яких його нащадків.

Рішення

Тому захоплювати виключення прийнято в порядку, зворотному успадкуванню: чим ближче клас до класу Exception, тим він нижче. Приклад:


def check_value(value):
    if value < 0:
        raise NegativeValueError(value)
    elif value > 100:
        raise ValueTooLargeError(value)
        
try:
    check_value(150)
except NegativeValueError as e:
    print(f"Сталося виключення: {e}")
except ApplicationError as e:
    print(f"Загальне виключення застосунку: {e}")
except Exception as e:
    print(f"Захоплення всіх виключень: {e}")

У цьому прикладі блоки except розташовані в порядку, що відповідає їх ієрархії успадкування: спочатку перехоплюються більш специфічні виключення, такі як NegativeValueError, потім більш загальні, такі як ApplicationError. Це дозволяє правильно обробляти виключення і уникати ситуацій, коли більш загальний обробник захоплює виключення до того, як його могли б обробити більш спеціалізовані блоки except.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ