Генерация ошибки python

Данный урок посвящен исключениям и работе с ними. Основное внимание уделено понятию исключения в языках программирования, обработке исключений в Python, их генерации и созданию пользовательских исключений.

Исключения в языках программирования

Исключениями (exceptions) в языках программирования называют проблемы, возникающие в ходе выполнения программы, которые допускают возможность дальнейшей ее работы в рамках основного алгоритма. Типичным примером исключения является деление на ноль, невозможность считать данные из файла (устройства), отсутствие доступной памяти, доступ к закрытой области памяти и т.п. Для обработки таких ситуаций в языках программирования, как правило, предусматривается специальный механизм, который называется обработка исключений (exception handling).

Исключения разделяют на синхронные и асинхронные. Синхронные исключения могут возникнуть только в определенных местах программы. Например, если у вас есть код, который открывает файл и считывает из него данные, то исключение типа “ошибка чтения данных” может произойти только в указанном куске кода. Асинхронные исключения могут возникнуть в любой момент работы программы, они, как правило, связаны с какими-либо аппаратными проблемами, либо приходом данных. В качестве примера можно привести сигнал отключения питания.

В языках программирования чаще всего предусматривается специальный механизм обработки исключений. Обработка может быть с возвратом, когда после обработки исключения выполнение программы продолжается с того места, где оно возникло. И обработка без возврата, в этом случае, при возникновении исключения, осуществляется переход в специальный, заранее подготовленный, блок кода.

Различают структурную и неструктурную обработку исключений. Неструктурная обработка предполагает регистрацию функции обработчика для каждого исключения, соответственно данная функция будет вызвана при возникновении конкретного исключения. Для структурной обработки язык программирования должен поддерживать специальные синтаксические конструкции, которые позволяют выделить код, который необходимо контролировать и код, который нужно выполнить при возникновении исключительной ситуации.

В Python выделяют два различных вида ошибок: синтаксические ошибки и исключения.

Синтаксические ошибки в Python

Синтаксические ошибки возникают в случае если программа написана с нарушениями требований Python к синтаксису. Определяются они в процессе парсинга программы. Ниже представлен пример с ошибочным написанием функции print.

>>> for i in range(10):
    prin("hello!")

Traceback (most recent call last):
  File "<pyshell#2>", line 2, in <module>
    prin("hello!")
NameError: name 'prin' is not defined

Исключения в Python

Второй вид ошибок – это исключения. Они возникают в случае если синтаксически программа корректна, но в процессе выполнения возникает ошибка (деление на ноль и т.п.). Более подробно про понятие исключения написано выше, в разделе “исключения в языках программирования”.

Пример исключения ZeroDivisionError, которое возникает при делении на 0.

>>> a = 10
>>> b = 0
>>> c = a / b
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    c = a / b
ZeroDivisionError: division by zero

В Python исключения являются определенным типом данных, через который пользователь (программист) получает информацию об ошибке. Если в коде программы исключение не обрабатывается, то приложение останавливается и в консоли печатается подробное описание произошедшей ошибки с указанием места в программе, где она произошла и тип этой ошибки.

Иерархия исключений в Python

Существует довольно большое количество встроенных типов исключений в языке Python, все они составляют определенную иерархию, которая выглядит так, как показано ниже.

BaseException
+– SystemExit
+– KeyboardInterrupt
+– GeneratorExit
+– Exception
     +– StopIteration
     +– StopAsyncIteration
     +– ArithmeticError
     |    +– FloatingPointError
     |    +– OverflowError
     |    +– ZeroDivisionError
     +– AssertionError
     +– AttributeError
     +– BufferError
     +– EOFError
     +– ImportError
          +– ModuleNotFoundError
     +– LookupError
     |    +– IndexError
     |    +– KeyError
     +– MemoryError
     +– NameError
     |    +– UnboundLocalError
     +– OSError
     |    +– BlockingIOError
     |    +– ChildProcessError
     |    +– ConnectionError
     |    |    +– BrokenPipeError
     |    |    +– ConnectionAbortedError
     |    |    +– ConnectionRefusedError
     |    |    +– ConnectionResetError
     |    +– FileExistsError
     |    +– FileNotFoundError
     |    +– InterruptedError
     |    +– IsADirectoryError
     |    +– NotADirectoryError
     |    +– PermissionError
     |    +– ProcessLookupError
     |    +– TimeoutError
     +– ReferenceError
     +– RuntimeError
     |    +– NotImplementedError
     |    +– RecursionError
     +– SyntaxError
     |    +– IndentationError
     |         +– TabError
     +– SystemError
     +– TypeError
     +– ValueError
     |    +– UnicodeError
     |         +– UnicodeDecodeError
     |         +– UnicodeEncodeError
     |         +– UnicodeTranslateError
     +– Warning
          +– DeprecationWarning
          +– PendingDeprecationWarning
          +– RuntimeWarning
          +– SyntaxWarning
          +– UserWarning
          +– FutureWarning
          +– ImportWarning
          +– UnicodeWarning
          +– BytesWarning
          +– ResourceWarning

Как видно из приведенной выше схемы, все исключения являются подклассом исключения BaseException. Более подробно об иерархии исключений и их описании можете прочитать здесь.

Обработка исключений в Python

Обработка исключений нужна для того, чтобы приложение не завершалось аварийно каждый раз, когда возникает исключение. Для этого блок кода, в котором возможно появление исключительной ситуации необходимо поместить во внутрь синтаксической конструкции try…except.

print("start")
try:
   val = int(input("input number: "))
   tmp = 10 / val
   print(tmp)
except Exception as e:
   print("Error! " + str(e))
print("stop")

В приведенной выше программе возможных два вида исключений – это ValueError, возникающее в случае, если на запрос программы “введите число”, вы введете строку, и ZeroDivisionError – если вы введете в качестве числа 0.

Вывод программы при вводе нулевого числа будет таким.

start input number: 0 Error! stop

Если бы инструкций try…except не было, то при выбросе любого из исключений программа аварийно завершится.

print("start")
val = int(input(“input number: “))
tmp = 10 / val
print(tmp)
print("stop")

Если ввести 0 на запрос приведенной выше программы, произойдет ее остановка с распечаткой сообщения об исключении.

start


input number: 0


Traceback (most recent call last):


 File “F:/work/programming/python/devpractice/tmp.py”, line 3, in <module>


   tmp = 10 / val


ZeroDivisionError: division by zero

Обратите внимание, надпись stop уже не печатается в конце вывода программы.

Согласно документу по языку Python, описывающему ошибки и исключения, оператор try работает следующим образом:

  • Вначале выполняется код, находящийся между операторами try и except.
  • Если в ходе его выполнения исключения не произошло, то код в блоке except пропускается, а код в блоке try выполняется весь до конца.
  • Если исключение происходит, то выполнение в рамках блока try прерывается и выполняется код в блоке except. При этом для оператора except можно указать, какие исключения можно обрабатывать в нем. При возникновении исключения, ищется именно тот блок except, который может обработать данное исключение.
  • Если среди except блоков нет подходящего для обработки исключения, то оно передается наружу из блока try. В случае, если обработчик исключения так и не будет найден, то исключение будет необработанным (unhandled exception) и программа аварийно остановится.

Для указания набора исключений, который должен обрабатывать данный блок except их необходимо перечислить в скобках (круглых) через запятую после оператора except.

Если бы мы в нашей программе хотели обрабатывать только ValueError и ZeroDivisionError, то программа выглядела бы так.

print("start")
try:
   val = int(input("input number: "))
   tmp = 10 / val
   print(tmp)
except(ValueError, ZeroDivisionError):
   print("Error!")
print("stop")

Или так, если хотим обрабатывать ValueError, ZeroDivisionError по отдельность, и, при этом, сохранить работоспособность при возникновении исключений отличных от вышеперечисленных.

print("start")
try:
   val = int(input("input number: "))
   tmp = 10 / val
   print(tmp)
except ValueError:
   print("ValueError!")
except ZeroDivisionError:
   print("ZeroDivisionError!")
except:
   print("Error!")
print("stop")

Существует возможность передать подробную информацию о произошедшем исключении в код внутри блока except.

rint("start")
try:
   val = int(input("input number: "))
   tmp = 10 / val
   print(tmp)
except ValueError as ve:
   print("ValueError! {0}".format(ve))
except ZeroDivisionError as zde:
   print("ZeroDivisionError! {0}".format(zde))
except Exception as ex:
   print("Error! {0}".format(ex))
print("stop")

Использование finally в обработке исключений

Для выполнения определенного программного кода при выходе из блока try/except, используйте оператор finally.

try:
   val = int(input("input number: "))
   tmp = 10 / val
   print(tmp)
except:
   print("Exception")
finally:
  print("Finally code")

Не зависимо от того, возникнет или нет во время выполнения кода в блоке try исключение, код в блоке finally все равно будет выполнен.

Если необходимо выполнить какой-то программный код, в случае если в процессе выполнения блока try не возникло исключений, то можно использовать оператор else.

try:
   f = open("tmp.txt", "r")
   for line in f:
       print(line)
   f.close()
except Exception as e:
   print(e)
else:
   print("File was readed")

Генерация исключений в Python

Для принудительной генерации исключения используется инструкция raise.

Самый простой пример работы с raise может выглядеть так.

try:
   raise Exception("Some exception")
except Exception as e:
   print("Exception exception " + str(e))

Таким образом, можно “вручную” вызывать исключения при необходимости.

Пользовательские исключения (User-defined Exceptions) в Python

В Python можно создавать собственные исключения. Такая практика позволяет увеличить гибкость процесса обработки ошибок в рамках той предметной области, для которой написана ваша программа.

Для реализации собственного типа исключения необходимо создать класс, являющийся наследником от одного из классов исключений.

class NegValException(Exception):
   pass

try:
   val = int(input("input positive number: "))
   if val < 0:
       raise NegValException("Neg val: " + str(val))
   print(val + 10)
except NegValException as e:
  print(e)

P.S.

Если вам интересна тема анализа данных, то мы рекомендуем ознакомиться с библиотекой Pandas. На нашем сайте вы можете найти вводные уроки по этой теме. Все уроки по библиотеке Pandas собраны в книге “Pandas. Работа с данными”.
Книга: Pandas. Работа с данными

<<< Python. Урок 10. Функции в Python   Python. Урок 12. Ввод-вывод данных. Работа с файлами>>>

Генерация исключений и создание своих типов исключений

Последнее обновление: 30.01.2022

Генерация исключений и оператор raise

Иногда возникает необходимость вручную сгенерировать то или иное исключение. Для этого применяется оператор raise. Например, сгенерируем исключение

try:
    number1 = int(input("Введите первое число: "))
    number2 = int(input("Введите второе число: "))
    if number2 == 0:
        raise Exception("Второе число не должно быть равно 0")
    print("Результат деления двух чисел:", number1/number2)
except ValueError:
    print("Введены некорректные данные")
except Exception as e:
    print(e)
print("Завершение программы")

Оператору raise передается объект BaseException — в данном случае объект Exception. В конструктор
этого типа можно ему передать сообщение, которое затем можно вывести пользователю. В итоге, если number2 будет равно 0, то сработает оператор
raise, который сгенерирует исключение. В итоге управление программой перейдет к блоку except, который обрабатывает
исключения типа Exception:

Введите первое число: 1
Введите второе число: 0
Второе число не должно быть равно 0
Завершение программы

Создание своих типов исключений

В языке Python мы не ограничены только встроенными типами исключений и можем, применяя наследование, при необходимости создавать свои
типы исключений. Например, возьмем следующий класс Person:

class Person:
    def __init__(self, name, age):
        self.__name = name  # устанавливаем имя
        self.__age = age   # устанавливаем возраст

    def display_info(self):
        print(f"Имя: {self.__name}  Возраст: {self.__age}")

Здесь класс Person в конструкторе получает значения для имени и возраста и присваивает их приватным переменным name и age.
Однако при создании объекта Person мы можем передать в конструктор некорректное с точки зрения логики значение — например, отрицательное число.
Одним из способов решения данной ситуации представляет генерация исключения при передаче некорректных значений.

Итак, определим следующий код программы:

class PersonAgeException(Exception):
    def __init__(self, age, minage, maxage):
        self.age = age
        self.minage = minage
        self.maxage = maxage

    def __str__(self):
        return f"Недопустимое значение: {self.age}. " \
               f"Возраст должен быть в диапазоне от {self.minage} до {self.maxage}"


class Person:
    def __init__(self, name, age):
        self.__name = name  # устанавливаем имя
        minage, maxage = 1, 110
        if minage < age < maxage:   # устанавливаем возраст, если передано корректное значение
            self.__age = age
        else:                       # иначе генерируем исключение
            raise PersonAgeException(age, minage, maxage)

    def display_info(self):
        print(f"Имя: {self.__name}  Возраст: {self.__age}")

try:
    tom = Person("Tom", 37)
    tom.display_info()  # Имя: Tom 	Возраст: 37

    bob = Person("Bob", -23)
    bob.display_info()
except PersonAgeException as e:
    print(e)    # Недопустимое значение: -23. Возраст должен быть в диапазоне от 1 до 110

В начале здесь определен класс PersonAgeException, который наследуется от класса Exception. Как правило, собственные классы исключений
наследуются от класса Exception. Класс PersonAgeException предназначен для исключений, связанных с возрастом пользователя.

В конструкторе PersonAgeException получаем три значения — собственное некорректное значение, которое послужило причиной исключения,
а также минимальное и максимальное значения возраста.

class PersonAgeException(Exception):
    def __init__(self, age, minage, maxage):
        self.age = age
        self.minage = minage
        self.maxage = maxage

    def __str__(self):
        return f"Недопустимое значение: {self.age}. " \
               f"Возраст должен быть в диапазоне от {self.minage} до {self.maxage}"

В функции __str__ определяем текстовое представление класса — по сути сообщение об ошибке.

В конструкторе класса Persoon проверяем переданное для возраста пользователя значение. И если это значение не соответствует
определенному диапазону, то генерируем исключение типа PersonAgeException:

raise PersonAgeException(age, minage, maxage)

При применении класса Person нам следует учитывать, что конструктор класса может сгенерировать исключение при передаче некорректного
значения. Поэтому создание объектов Person обертывается в конструкцию try..except:

try:
    tom = Person("Tom", 37)
    tom.display_info()  # Имя: Tom 	Возраст: 37

    bob = Person("Bob", -23)  # генерируется исключение типа PersonAgeException
    bob.display_info()
except PersonAgeException as e:
    print(e)    # Недопустимое значение: -23. Возраст должен быть в диапазоне от 1 до 110

И если при вызове конструктора Person будет сгенерировано исключение типа PersonAgeException, то управление программой перейдет к
блоку except, который обрабатывает исключения типа PersonAgeException в виде вывода информации об исключении на консоль.

How do I manually throw/raise an exception in Python?

Use the most specific Exception constructor that semantically fits your issue.

Be specific in your message, e.g.:

raise ValueError('A very specific bad thing happened.')

Don’t raise generic exceptions

Avoid raising a generic Exception. To catch it, you’ll have to catch all other more specific exceptions that subclass it.

Problem 1: Hiding bugs

raise Exception('I know Python!') # Don't! If you catch, likely to hide bugs.

For example:

def demo_bad_catch():
    try:
        raise ValueError('Represents a hidden bug, do not catch this')
        raise Exception('This is the exception you expect to handle')
    except Exception as error:
        print('Caught this error: ' + repr(error))

>>> demo_bad_catch()
Caught this error: ValueError('Represents a hidden bug, do not catch this',)

Problem 2: Won’t catch

And more specific catches won’t catch the general exception:

def demo_no_catch():
    try:
        raise Exception('general exceptions not caught by specific handling')
    except ValueError as e:
        print('we will not catch exception: Exception')
 

>>> demo_no_catch()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in demo_no_catch
Exception: general exceptions not caught by specific handling

Best Practices: raise statement

Instead, use the most specific Exception constructor that semantically fits your issue.

raise ValueError('A very specific bad thing happened')

which also handily allows an arbitrary number of arguments to be passed to the constructor:

raise ValueError('A very specific bad thing happened', 'foo', 'bar', 'baz') 

These arguments are accessed by the args attribute on the Exception object. For example:

try:
    some_code_that_may_raise_our_value_error()
except ValueError as err:
    print(err.args)

prints

('message', 'foo', 'bar', 'baz')    

In Python 2.5, an actual message attribute was added to BaseException in favor of encouraging users to subclass Exceptions and stop using args, but the introduction of message and the original deprecation of args has been retracted.

Best Practices: except clause

When inside an except clause, you might want to, for example, log that a specific type of error happened, and then re-raise. The best way to do this while preserving the stack trace is to use a bare raise statement. For example:

logger = logging.getLogger(__name__)

try:
    do_something_in_app_that_breaks_easily()
except AppError as error:
    logger.error(error)
    raise                 # just this!
    # raise AppError      # Don't do this, you'll lose the stack trace!

Don’t modify your errors… but if you insist.

You can preserve the stacktrace (and error value) with sys.exc_info(), but this is way more error prone and has compatibility problems between Python 2 and 3, prefer to use a bare raise to re-raise.

To explain — the sys.exc_info() returns the type, value, and traceback.

type, value, traceback = sys.exc_info()

This is the syntax in Python 2 — note this is not compatible with Python 3:

raise AppError, error, sys.exc_info()[2] # avoid this.
# Equivalently, as error *is* the second object:
raise sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]

If you want to, you can modify what happens with your new raise — e.g. setting new args for the instance:

def error():
    raise ValueError('oops!')

def catch_error_modify_message():
    try:
        error()
    except ValueError:
        error_type, error_instance, traceback = sys.exc_info()
        error_instance.args = (error_instance.args[0] + ' <modification>',)
        raise error_type, error_instance, traceback

And we have preserved the whole traceback while modifying the args. Note that this is not a best practice and it is invalid syntax in Python 3 (making keeping compatibility much harder to work around).

>>> catch_error_modify_message()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in catch_error_modify_message
  File "<stdin>", line 2, in error
ValueError: oops! <modification>

In Python 3:

raise error.with_traceback(sys.exc_info()[2])

Again: avoid manually manipulating tracebacks. It’s less efficient and more error prone. And if you’re using threading and sys.exc_info you may even get the wrong traceback (especially if you’re using exception handling for control flow — which I’d personally tend to avoid.)

Python 3, Exception chaining

In Python 3, you can chain Exceptions, which preserve tracebacks:

raise RuntimeError('specific message') from error

Be aware:

  • this does allow changing the error type raised, and
  • this is not compatible with Python 2.

Deprecated Methods:

These can easily hide and even get into production code. You want to raise an exception, and doing them will raise an exception, but not the one intended!

Valid in Python 2, but not in Python 3 is the following:

raise ValueError, 'message' # Don't do this, it's deprecated!

Only valid in much older versions of Python (2.4 and lower), you may still see people raising strings:

raise 'message' # really really wrong. don't do this.

In all modern versions, this will actually raise a TypeError, because you’re not raising a BaseException type. If you’re not checking for the right exception and don’t have a reviewer that’s aware of the issue, it could get into production.

Example Usage

I raise Exceptions to warn consumers of my API if they’re using it incorrectly:

def api_func(foo):
    '''foo should be either 'baz' or 'bar'. returns something very useful.'''
    if foo not in _ALLOWED_ARGS:
        raise ValueError('{foo} wrong, use "baz" or "bar"'.format(foo=repr(foo)))

Create your own error types when apropos

«I want to make an error on purpose, so that it would go into the except»

You can create your own error types, if you want to indicate something specific is wrong with your application, just subclass the appropriate point in the exception hierarchy:

class MyAppLookupError(LookupError):
    '''raise this when there's a lookup error for my app'''

and usage:

if important_key not in resource_dict and not ok_to_be_missing:
    raise MyAppLookupError('resource is missing, and that is not ok.')

Курс по Python ООП: https://stepik.org/a/116336

Мы продолжаем
тему исключений. Во всех наших предыдущих примерах исключение возникало в
результате ошибочных ситуаций во время работы программы, например, деления на
ноль:

print("Куда ты скачешь, гордый конь,")
print("И где опустишь ты копыта?")
print("О мощный властелин судьбы!")
1/0
print("Не так ли ты над самой бездной")
print("На высоте, уздой железной")
print("Россию поднял на дыбы?")

Но как эта
операция деления формирует само исключение? Для этого в языке Python имеется
конструкция (оператор)

raise

которая и
порождает указанные типы исключений. В самом простом варианте, мы можем вместо
деления на ноль записать этот оператор и указать тип исключения ZeroDivisionError:

raise ZeroDivisionError("Деление на ноль")

Результат
выполнения программы будет тем же – она остановится на конструкции raise. Только
сообщение об ошибке теперь будет на русском языке – та строка, что мы указали
при формировании объекта класса ZeroDivisionError. То есть, после
оператора raise мы можем
прописывать нужный нам класс исключения с собственными параметрами. Также можно
просто указывать класс, не прописывая каких-либо параметров:

Здесь у нас
также создается экземпляр, но без параметров. Раз это так, значит, можно
заранее создать экземпляр класса:

e = ZeroDivisionError("Деление на ноль")

а, затем,
сгенерировать это исключение:

Вообще, мы можем
использовать любой класс в качестве исключения, унаследованного от базового
класса:

BaseException

Например, если
просто указать строку после оператора raise:

то интерпретатор
Python как раз это нам
и укажет:

TypeError:
exceptions must derive from BaseException

То есть, после raise должен
находиться экземпляр класса исключения, а не какой-то произвольный объект.

Когда нам может
понадобиться оператор raise? И разве сам язык Python не может
генерировать нужные исключения при возникновении ошибок? Часто именно так и
происходит. Например, если мы будем делать некорректные операции, вроде:

то автоматически
возникают ошибки заданного типа. Но прописать исключения на все случаи жизни
невозможно. И если в качестве примера взять все тот же класс печати данных:

То, в частности,
метод send_data() может
генерировать свое исключение, если по каким-то причинам данные не были
отправлены принтеру. В качестве демонстрации я приведу гипотетический класс PrintData для работы с
принтером:

class PrintData:
    def print(self, data):
        self.send_data(data)
        print(f"печать: {str(data)}")
 
    def send_data(self, data):
        if not self.send_to_print(data):
            raise Exception("принтер не отвечает")
 
    def send_to_print(self, data):
        return False

Как раз здесь мы
генерируем исключение, если данные не могут быть отправлены принтеру. Затем,
это исключение может быть обработано на любом уровне стека вызова. Например,
если далее создать экземпляр этого класса и вызвать метод print():

p = PrintData()
p.print("123")

То мы увидим
сформированное нами исключение. Как вы понимаете, в язык Python не встроена по
умолчанию возможность генерации исключения при взаимодействии с принтером. Это приходится
делать уже самому программисту с помощью оператора raise. Вот для этого
он и нужен.

Создание пользовательских исключений

В нашем
гипотетическом классе PrintData исключение генерируется с помощью класса Exception. Почему именно
он? Если мы посмотрим на иерархию классов исключений языка Python, то здесь во
главе стоит базовый класс BaseException:

Остальные классы
наследуются от него и имеют строгую специализацию, кроме, разве что, класса Exception, который
является общим для большого разнообразия типов исключений в момент выполнения
программы. Так почему же мы выбрали класс Exception, а не BaseException? Дело в том,
что классы SystemExit, GeneratorExit и KeyboardInterrupt являются весьма
специфичными и, обычно, они не используются при обработке собственных
исключений. Поэтому, целесообразно выбирать именно класс Exception для
формирования новых собственных классов исключений. Что мы сейчас и сделаем.

Итак, чтобы
сформировать свой новый тип исключения, нужно прописать класс, который
рекомендуется наследовать от класса Exception. В самом
простом варианте достаточно просто описать иерархию:

class ExceptionPrintSendData(Exception):
    """Класс исключения при отправке данных принтеру"""

И далее в
программе использовать этот новый класс:

    def send_data(self, data):
        if not self.send_to_print(data):
            raise ExceptionPrintSendData("принтер не отвечает")

Соответственно,
ниже в программе, мы можем обработать этот тип ошибки, просто указав имя нашего
нового класса:

p = PrintData()
 
try:
    p.print("123")
except ExceptionPrintSendData:
    print("Ошибка печати")

Видите, как это
здорово! Мы создали новый тип исключения, просто прописав новый класс. И
благодаря этому можем отличить ошибку передачи данных принтеру от каких-либо
других ошибок.

Разумеется, мы
поймаем эту же ошибку, если укажем базовый класс Exception, но пропустим,
если указать какой-либо другой независимый класс исключения, иерархически не
связанный с нашим, например, ArithmeticError.

Кроме того, мы
можем расширить функционал класса ExceptionPrintSendData. Давайте добавим в
него конструктор. Он прописывается для произвольного числа аргументов:

class ExceptionPrintSendData(Exception):
    """Класс исключения при отправке данных принтеру"""
    def __init__(self, *args):
        self.message = args[0] if args else None

А также
магически метод__str__ для представления ошибки в консоли:

    def __str__(self):
        return f"Ошибка: {self.message}"

Если теперь
убрать блок try/except и вызвать метод
print(), то увидим наш вариант отображения ошибки в консоли:

p = PrintData()
p.print("123")

Это лишь пример
расширения функционала класса исключения. В каждом конкретном случае
программист может написать любую свою реализацию.

Наконец, пользовательские
классы исключений дают возможность создавать свою иерархию исключений. В
частности, в нашем примере, можно прописать общий класс исключений для принтера
ExceptionPrint:

class ExceptionPrint(Exception):
    """Общий класс исключения принтера"""

А, затем,
остальные, более конкретные типы наследовать от него:

class ExceptionPrintSendData(ExceptionPrint):
    """Класс исключения при отправке данных принтеру"""

В результате, в
блоке except мы можем
отлавливать как конкретные типы ошибок, так и общие, связанные с принтером:

p = PrintData()
 
try:
    p.print("123")
except ExceptionPrintSendData as e:
    print(e)
except ExceptionPrint:
    print("Ошибка печати")

Такой подход
дает гибкий механизм обработки собственных типов исключений, благодаря чему,
программа становится более понятной и структурированной.

Курс по Python ООП: https://stepik.org/a/116336

Видео по теме

Python как генерировать исключительные ситуации

Python предлагает механизм обработки исключений, который использует ключевые слова try, except, finally, raise и assert.

Генерация исключений с помощью raise

Ключевое слово raise в Python используется для генерации исключения в программе. Это может быть стандартное исключение Python или специально определенное вами исключение.

        
            x = 10
            if x > 5:
                raise Exception('x не должно превышать 5. Значение x было: {}'.format(x))
        
    

Генерация исключений с помощью assert

В Python ключевое слово assert также используется для генерации исключения. assert генерирует исключение AssertionError, если условие логического выражения не выполняется.

        
            x = 10
            assert x < 5, 'x не должно превышать 5. Значение x было: {}'.format(x)
        
    

Создание собственных исключений

Вы также можете определить свои собственные исключения в Python. Для этого вы должны определить новый класс исключений, который является прямым или косвенным наследником класса Exception.

        
            class ValueTooHighError(Exception):
                pass

            x = 10
            if x > 5:
                raise ValueTooHighError('x не должно превышать 5. Значение x было: {}'.format(x))
        
    

Обработка исключений — это важная часть написания надежного и безопасного кода. Благодаря этим инструментам вы можете контролировать поведение вашего программного обеспечения даже в случае неожиданных ситуаций.

python как генерировать исключительные ситуации

Понравилась статья? Поделить с друзьями:
  • Генетическая ошибка нет лица
  • Геномед нипт ошибки
  • Генерация электронной подписи ошибка генерации сертификата
  • Генные мутации являются результатом ошибок при
  • Генерация ошибки vba