Руководство по обработке исключений Python

каталога в Python Изучение

В этой статье мы рассмотрим, как обрабатывать ошибки и исключения в Python — концепцию, известную как «обработка исключений».

Обычно при программировании на Python вы сталкиваетесь с двумя типами ошибок: синтаксическими ошибками и исключениями.

Любая ошибка, возникающая из-за неправильного синтаксиса, отступа или структуры программирования, часто рассматривается как синтаксическая ошибка. При возникновении синтаксической ошибки программа аварийно завершает работу в момент возникновения синтаксической ошибки.

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

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

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

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

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

Некоторые стандартные исключения Python

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

серийный номер Имя исключения Описание
1 Exception Все пользовательские исключения также должны быть производными от этого класса.
2 ArithmeticError Базовый класс для тех встроенных исключений, которые возникают при различных арифметических ошибках.
3 BufferError Возникает, когда операция, связанная с буфером, не может быть выполнена.
4 LookupError Базовый класс для исключений, возникающих, когда ключ или индекс, используемые в сопоставлении или последовательности, недействительны.
5 AssertionError Возникает, когда оператор assert терпит неудачу.
6 AttributeError Возникает при сбое ссылки или назначения атрибута.
7 ImportError Возникает, когда оператор импорта испытывает проблемы с загрузкой модуля.
8 IndexError Возникает, когда индекс последовательности выходит за допустимые пределы.
9 KeyError Возникает, когда ключ сопоставления (словарь) не найден в наборе существующих ключей.
10 NameError Возникает, когда локальное или глобальное имя не найдено.
11 OverflowError Возникает, когда результат арифметической операции слишком велик для представления.
12 RuntimeError Возникает при обнаружении ошибки, не подпадающей ни под одну из других категорий.
13 StopIteration Вызывается встроенной функцией next()и методом итератора __next__(), чтобы сигнализировать о том, что итератор больше не создает элементы.
14 SyntaxError Возникает, когда синтаксический анализатор обнаруживает синтаксическую ошибку.
15 TypeError Возникает, когда операция или функция применяется к объекту неподходящего типа.
16 ValueError Возникает, когда операция или функция получает аргумент правильного типа, но с неподходящим значением.
17 ZeroDivisionError Возникает, когда второй аргумент деления или операции по модулю равен нулю.
18 FileExistsError Возникает при попытке создать файл или каталог, который уже существует.
19 FileNotFoundError Возникает, когда запрашивается файл или каталог, но он не существует.

Обработка исключений Python с помощью операторов try и exclude

Блоки tryи exceptиспользуются для обработки исключений в Python. Синтаксис может выглядеть так:

try:
    # some code that could cause an exception
except: 
    # some code to execute to handle exception

Блок tryсодержит участок кода, который может вызвать исключение, а exceptблок содержит некоторый код, обрабатывающий исключение.

Давайте рассмотрим простой пример ниже:

print(3/0)

Приведенный выше код будет генерировать сообщение об ошибке при завершении программы:

Traceback (most recent call last):
  File "/home/ini/Dev/Tutorial/sitepoint/exception.py", line 53, in <module>
    print(3/0)
ZeroDivisionError: division by zero

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

try:
    print(3/0)
except ZeroDivisionError:
    print("Cannot divide number by Zero")

В приведенном выше примере мы помещаем первый оператор печати в tryблок. Фрагмент кода в этом блоке вызовет исключение, потому что деление числа на ноль не имеет смысла. Блок exceptпоймает исключение, возникшее в tryблоке. Блоки tryи exceptчасто используются вместе для обработки исключений в Python. Вместо предыдущего сообщения об ошибке, которое было сгенерировано, в консоли просто напечатано «Невозможно разделить число на ноль».

Несколько исключений Python

Бывают случаи, когда два или более exceptблока используются для перехвата разных исключений в Python. Несколько блоков исключений помогают нам перехватывать определенные исключения и по-разному обрабатывать их в нашей программе:

try:
    number = 'one'
    print(number + 1)
    print(block)
except NameError:
    print("Name is undefined here")
except TypeError:
    print("Can't concatenate string and int")

Вот вывод кода выше:

Can't concatenate string and int

В приведенном выше примере у нас есть два exceptблока, определяющих типы исключений, которые мы хотим обрабатывать: NameErrorи TypeError. Первый оператор печати в tryблоке вызывает TypeErrorисключение. Интерпретатор Python проверяет каждое exceptпредложение, чтобы найти соответствующий класс исключения, который обрабатывается вторым exceptблоком. В консоли выводится сообщение «Невозможно объединить строку и целое число».

Второй оператор печати в tryблоке пропускается из-за возникновения исключения. Однако любой код после последнего exceptпредложения будет выполнен:

try:
    number = 'one'
    print(number + 1)
    print(block)
except NameError:
    print("Name is undefined here")
except TypeError:
    print("Can't concatenate string and int")

for name in ['Chris', 'Kwame', 'Adwoa', 'Bolaji']:
    print(name, end=" ")

Вот вывод кода выше:

Can't concatenate string and int
Chris Kwame Adwoa Bolaji

Цикл forпосле блоков tryи exceptвыполняется, потому что исключение было обработано.

Общий Python, за исключением

У нас может быть общий exceptблок для перехвата всех исключений в Python. Общий exceptблок можно использовать вместе с другими конкретными exceptблоками в нашей программе для перехвата необработанных исключений. Логично разместить самое общее exceptпредложение после всех конкретных exceptблоков. Это сработает, когда возникнет необработанное исключение. Давайте пересмотрим наш предыдущий пример с общим exceptблоком, идущим последним:

names = ['Chris', 'Kwame', 'Adwoa', 'Bolaji']
try:
    print(names[6])
    number = 'one'
    print(number + 1)
    print(block)
except NameError:
    print("Name is undefined here")
except TypeError:
    print("Can't concatenate string and int")
except:
    print('Sorry an error occured somewhere!')

for name in names:
    print(name, end=" ")

Вот вывод кода выше:

Sorry an error occured somewhere!
Chris Kwame Adwoa Bolaji

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

Оператор повышения

Иногда в наших программах на Python мы можем захотеть вызвать исключения в определенных условиях, которые не соответствуют нашим требованиям, используя raiseключевое слово. Оператор raiseсостоит из самого ключевого слова, экземпляра исключения и необязательного аргумента. Давайте возьмем фрагмент кода ниже:

def validate_password(password):
    if len(password) < 8:
        raise ValueError("Password characters less than 8")
    return password

try:
    user_password = input('Enter a password: ')
    validate_password(user_password)
except ValueError:
    print('Password should have more characters')

Проверяет raise ValueError, соответствует ли пароль необходимой длине, и вызывает указанное исключение, если условие не выполняется. Stack OverFlow исследует, почему можно вызывать исключения, а не просто выводить их на консоль:

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

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

Предложение else

Условие elseможет быть добавлено в стандарт tryи exceptблоки. Он ставится после exceptпредложения. Предложение elseсодержит код, который мы хотим выполнить, если tryоператор не вызывает исключение. Рассмотрим следующий код:

try:
    number = int(input('Enter a number: '))
    if number % 2 != 0:
        raise ValueError
except ValueError:
    print("Number must be even")
else:
    square = number ** 2
    print(square)

Когда пользователь вводит четное число, наш код запускается без возникновения исключений. Затем elseпредложение выполняется. Теперь у нас есть квадрат нашего четного числа, напечатанный в консоли. Однако исключения, которые могут возникнуть в elseпредложении, не обрабатываются предыдущими exceptблоками.

Finally пункт

Предложение finally может быть добавлено в блоки tryи exceptи должно использоваться там, где это необходимо. Код в finallyпредложении всегда выполняется независимо от того, возникает исключение или нет. См. фрагмент кода ниже:

try:
    with open('robots.txt', 'r', encoding='UTF-8') as f:
        first_line = f.readline()
except IOError: 
    print('File not found!')
else:
    upper_case = first_line.upper()
    print(upper_case.index('x'))
finally:
    print('The Python program ends here!')

Вот вывод кода выше:

The Python program ends here!
Traceback (most recent call last):
  File "/home/ini/Dev/python/python_projects/extra.py", line 89, in <module>
    print(upper_case.index('x'))
ValueError: substring not found

В приведенном выше примере мы пытаемся прочитать файл robots.txtв tryпредложении. Поскольку исключений не возникает, код в предложении elseвыполняется. В предложении возникает исключение, elseпоскольку подстрока xне найдена в переменной upper_case. Когда для обработки исключения нет предложения exclude (как видно из приведенного выше фрагмента кода), finallyсначала выполняется предложение, а затем повторно вызывается исключение.

Документация Python объясняет это так:

Исключение могло возникнуть во время выполнения предложения exceptor else. Опять же, исключение повторно вызывается после того, как finallyпредложение было выполнено.

Группы исключений

ExceptionGroupстал доступен в Python 3.11. Он предоставляет средства для создания нескольких несвязанных исключений. Предпочтительный синтаксис для обработки ExceptionGroup— except*. Синтаксис групп исключений выглядит следующим образом:

ExceptionGroup(msg, excs)

При инициализации группы исключений принимают два аргумента msgи excs:

  • msg: описательное сообщение
  • excs: последовательность подгрупп исключений

Давайте создадим экземпляр ExceptionGroup:

eg = ExceptionGroup('group one', [NameError("name not defined"), TypeError("type mismatch")])

При создании экземпляра группы исключений список подгрупп исключений не может быть пустым. Мы поднимем экземпляр группы исключений, которую мы создали ранее:

raise eg

Вот вывод кода выше:

+ Exception Group Traceback (most recent call last):
|   File "<string>", line 10, in <module>
  | ExceptionGroup: group one (2 sub-exceptions)
  +-+---------------- 1 ----------------
    | NameError: name not defined
    +---------------- 2 ----------------
    | TypeError: type mismatch
    +------------------------------------

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

Как указывалось ранее, ExceptionGroupлучше обрабатывать предложение except*, поскольку оно может выбрать каждое конкретное исключение в группе исключений. Общее exceptпредложение будет обрабатывать группу исключений только как единое целое, не будучи конкретным.

См. фрагмент кода ниже:

try:
    raise ExceptionGroup('exception group', [NameError("name not defined"), TypeError("type mismatch"), ValueError("invalid input")])
except* NameError as e:
    print("NameError handled here.")
except* TypeError as e:
    print("TypeError handled here.")
except* ValueError:
    print("ValueError handled here.")

Вот вывод этого кода:

NameError handled here.
TypeError handled here.
ValueError handled here.

Каждое except*предложение обрабатывает целевую подгруппу исключений в группе исключений. Любая необработанная подгруппа вызовет повторное исключение.

Пользовательские исключения в Python

Встроенные исключения — это здорово, но для нашего программного проекта могут потребоваться пользовательские исключения. Python позволяет нам создавать пользовательские исключения в соответствии с нашими потребностями. Документация Python гласит:

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

Пользовательские исключения получаются путем наследования Exceptionкласса Python. Синтаксис пользовательского исключения выглядит следующим образом:

class CustomExceptionName(Exception):
    pass
try:
    pass
except CustomExceptionName:
    pass

Давайте создадим собственное исключение и используем его в нашем коде в следующем примере:

class GreaterThanTenError(Exception):
    pass

try:
    number = int(input("Enter a number: "))
    if number > 10:
        raise GreaterThanTenError
except GreaterThanTenError:
    print("Input greater than 10")
else:
    for i in range(number):
        print(i ** 2, end=" ")
finally:
    print()
    print("The Python program ends here")

В приведенном выше примере мы создаем собственный класс с именем исключения, называемым GreaterThanTenException, который наследуется от Exceptionсуперкласса. Помещаем в него некоторый код, который может вызвать исключение в tryблоке. Блок except— это наш обработчик исключений. В elseпредложении есть код, который должен быть выполнен, если исключение не выброшено. И, наконец, finallyпункт выполняется независимо от результата.

Если пользователь нашей программы Python введет число больше 10, GreaterThanTenErrorбудет поднято значение a. Предложение будет обрабатывать исключения, а затем выполняется exceptоператор печати в предложении.finally

Заключение

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

Мы также узнали, что операторы tryи exceptявляются стандартным синтаксисом для обработки исключений в Python.

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

Читайте также:  Таблицы HTML: как создавать и стилизовать таблицы с помощью HTML
Оцените статью
bestprogrammer.ru
Добавить комментарий