X type error codes



Значения исключений и ошибок в Python

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

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

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

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

Ошибки могут быть разных видов:

  • Синтаксические
  • Недостаточно памяти
  • Ошибки рекурсии
  • Исключения

Разберем их по очереди.

Синтаксические ошибки (SyntaxError)

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

Рассмотрим на примере.

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

Недостаточно памяти (OutofMemoryError)

Ошибки памяти чаще всего связаны с оперативной памятью компьютера и относятся к структуре данных под названием “Куча” ( heap ). Если есть крупные объекты (или) ссылки на подобные, то с большой долей вероятности возникнет ошибка OutofMemory . Она может появиться по нескольким причинам:

  • Использование 32-битной архитектуры Python (максимальный объем выделенной памяти невысокий, между 2 и 4 ГБ);
  • Загрузка файла большого размера;
  • Запуск модели машинного обучения/глубокого обучения и много другое;

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

Но поскольку Python использует архитектуру управления памятью из языка C (функция malloc() ), не факт, что все процессы восстановятся — в некоторых случаях MemoryError приведет к остановке. Следовательно, обрабатывать такие ошибки не рекомендуется, и это не считается хорошей практикой.

Ошибка рекурсии (RecursionError)

Эта ошибка связана со стеком и происходит при вызове функций. Как и предполагает название, ошибка рекурсии возникает, когда внутри друг друга исполняется много методов (один из которых — с бесконечной рекурсией), но это ограничено размером стека.

Все локальные переменные и методы размещаются в стеке. Для каждого вызова метода создается стековый кадр (фрейм), внутрь которого помещаются данные переменной или результат вызова метода. Когда исполнение метода завершается, его элемент удаляется.

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

Ошибка отступа (IndentationError)

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

Исключения

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

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

Ошибка типа (TypeError)

Ошибка деления на ноль (ZeroDivisionError)

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

Оставшаяся часть строки с ошибкой предлагает подробности о причине ошибки на основе ее типа.

Теперь рассмотрим встроенные исключения Python.

Встроенные исключения

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

  • Try : он запускает блок кода, в котором ожидается ошибка.
  • Except : здесь определяется тип исключения, который ожидается в блоке try (встроенный или созданный).
  • Else : если исключений нет, тогда исполняется этот блок (его можно воспринимать как средство для запуска кода в том случае, если ожидается, что часть кода приведет к исключению).
  • Finally : вне зависимости от того, будет ли исключение или нет, этот блок кода исполняется всегда.

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

Ошибка прерывания с клавиатуры (KeyboardInterrupt)

Исключение KeyboardInterrupt вызывается при попытке остановить программу с помощью сочетания Ctrl + C или Ctrl + Z в командной строке или ядре в Jupyter Notebook. Иногда это происходит неумышленно и подобная обработка поможет избежать подобных ситуаций.

Читайте также:  Node express 404 error

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

Стандартные ошибки (StandardError)

Рассмотрим некоторые базовые ошибки в программировании.

Арифметические ошибки (ArithmeticError)

  • Ошибка деления на ноль (Zero Division);
  • Ошибка переполнения (OverFlow);
  • Ошибка плавающей точки (Floating Point);

Все перечисленные выше исключения относятся к классу Arithmetic и вызываются при ошибках в арифметических операциях.

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

Когда делитель (второй аргумент операции деления) или знаменатель равны нулю, тогда результатом будет ошибка деления на ноль.

Переполнение (OverflowError)

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

Ошибка утверждения (AssertionError)

Когда инструкция утверждения не верна, вызывается ошибка утверждения.

Рассмотрим пример. Предположим, есть две переменные: a и b . Их нужно сравнить. Чтобы проверить, равны ли они, необходимо использовать ключевое слово assert , что приведет к вызову исключения Assertion в том случае, если выражение будет ложным.

Ошибка атрибута (AttributeError)

При попытке сослаться на несуществующий атрибут программа вернет ошибку атрибута. В следующем примере можно увидеть, что у объекта класса Attributes нет атрибута с именем attribute .

Ошибка импорта (ModuleNotFoundError)

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

Ошибка поиска (LookupError)

LockupError выступает базовым классом для исключений, которые происходят, когда key или index используются для связывания или последовательность списка/словаря неверна или не существует.

Здесь есть два вида исключений:

  • Ошибка индекса ( IndexError );
  • Ошибка ключа ( KeyError );

Ошибка ключа

Если ключа, к которому нужно получить доступ, не оказывается в словаре, вызывается исключение KeyError .

Ошибка индекса

Если пытаться получить доступ к индексу (последовательности) списка, которого не существует в этом списке или находится вне его диапазона, будет вызвана ошибка индекса (IndexError: list index out of range python).

Ошибка памяти (MemoryError)

Как уже упоминалось, ошибка памяти вызывается, когда операции не хватает памяти для выполнения.

Ошибка имени (NameError)

Ошибка имени возникает, когда локальное или глобальное имя не находится.

В следующем примере переменная ans не определена. Результатом будет ошибка NameError .

Ошибка выполнения (Runtime Error)

Ошибка «NotImplementedError»
Ошибка выполнения служит базовым классом для ошибки NotImplemented . Абстрактные методы определенного пользователем класса вызывают это исключение, когда производные методы перезаписывают оригинальный.

Ошибка типа (TypeError)

Ошибка типа вызывается при попытке объединить два несовместимых операнда или объекта.

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

Ошибка значения (ValueError)

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

В этом примере встроенная операция float получат аргумент, представляющий собой последовательность символов (значение), что является недопустимым значением для типа: число с плавающей точкой.

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

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

Это можно сделать, создав новый класс, который будет наследовать из класса Exception в Python.

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

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

У использования исключений есть свои побочные эффекты, как, например, то, что программы с блоками try-except работают медленнее, а количество кода возрастает.

Дальше пример, где модуль Python timeit используется для проверки времени исполнения 2 разных инструкций. В stmt1 для обработки ZeroDivisionError используется try-except, а в stmt2 — if . Затем они выполняются 10000 раз с переменной a=0 . Суть в том, чтобы показать разницу во времени исполнения инструкций. Так, stmt1 с обработкой исключений занимает больше времени чем stmt2 , который просто проверяет значение и не делает ничего, если условие не выполнено.

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

Выводы!

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

Обработка исключений — один из основных факторов, который делает код готовым к развертыванию. Это простая концепция, построенная всего на 4 блоках: try выискивает исключения, а except их обрабатывает.

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

Источник

Разбираем BGP NOTIFICATION по RFC

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

Читайте также:  Source engine error model

Не могу сказать, что я это помню, ещё не могу сказать что это мне мешает в работе. Я даже не могу сказать, что мне приходится часто видеть заголовки в каком-то необработанном виде, потому что, как правило, сообщения в syslog или на консоли уже переформатированы в связные английские предложения. Но, иногда, приходиться смотреть глубже, например, этот год был урожайный на подобные сообщения:

Cisco, то же с другой стороны

Попробуем разобрать это руками как написано в RFC4271. Не будем искать причину — просто разбор заголовков. Будет много цитат и, скорее всего, ничего нового для тех кто уже это умеет делать. Для остальных читаем дальше.

Чтобы внести разнообразие не ограничимся одним сообщением и разберём ещё вот это issue с GitHub FRRouting:

Что мы можем прочитать? Видим тип сообщения, его значение и подзначение, IP адрес соседства (который нам и так известен) и шестнадцатеричная строка, которую мы не понимаем.

Начнём с главного с сайта IANA где есть все нужные коды с отсылкой к RFC4271. Если набраться сил и прочитать RFC от корки до корки, то всё должно стать понятно, но мы попытаемся разобраться только в формате наших двух сообщений не затрагивая поведенческие аспекты.

Разбираем NOTIFICATION

Из содержания, по названию, нам подходит пункт 4.5 NOTIFICATION Message Format. Открыв который действительно находим формат нужного нам заголовка и список всех кодов с ссылкой на соответствующие разделы (дальше всё цитирование спрячем под спойлеры):

Наш раздел 6.3 UPDATE Message Error с кодом ошибки 3. Видим его во всех сообщениях, вместе с уточняющим кодом:

code 3/4 (update: attribute flags error) — 0000 0000 ffff ffff ffff ffff ffff ffff ffff ffff 0020 0303 04e0 0708 0003 02ed 5bdc 3f01

code 3 (Update Message Error) subcode 4 (attribute flags error), Data: e0 07 08 00 03 02 ed 5b dc 3f 01

3/5 (UPDATE Message Error/Attribute Length Error) 3298 bytes 50 02 0c de 02 ff 00 00 0c b9 00 00 00 ae 00 04 00 3e 00 04 00 3e 00 04 00 35 00 04 00 35 . очень много раз 00 04 00 35

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

В нашем случае — используемые флаги не могут быть использованы c данным атрибутом:

и — фактическая длина атрибута не совпадает с ожидаемой:

Самое важное, что тут написано и что нам поможет в дальнейшем это то, что помимо кодов ошибок в сообщении ДОЛЖЕН присутствовать ошибочный атрибут из UPDATE сообщения в поле data в формате TLV (тип, длина, значение). Та самая шестнадцатеричная строка которую мы пока не можем интерпретировать. Однако, у нас по прежнему есть проблема в идентификации этого поля, связанная теперь с различными соглашениями принятыми производителями устройств для отображения журнала логов.

В примере с Cisco, явно указывается начало словом «Data»:
code 3 (Update Message Error) subcode 4 (attribute flags error), Data : e0 07 08 00 03 02 ed 5b dc 3f 01

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

Поднимемся выше по иерархии и начнём читать с начала раздела 4.1:

Каждое сообщение начинается с поля:

длиной в 16 байт и состоящее из всех единиц ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff . Такой же паттерн мы видим в логе Ericsson:
code 3/4 (update: attribute flags error) — 0000 0000 ( ffff ffff ffff ffff ffff ffff ffff ffff ) 0020 0303 04e0 0708 0003 02ed 5bdc 3f01

Далее поле длины в два байта:
code 3/4 (update: attribute flags error) — 0000 0000 ffff ffff ffff ffff ffff ffff ffff ffff ( 0020 ) 0303 04e0 0708 0003 02ed 5bdc 3f01 , со значением 32 десятичные, что совпадает с расшифровкой из журнала notification msg sent (nbr 192.0.2.1, context 0x40030044 32 bytes , а ещё дальше :

и мы знаем что оно номер 3 — NOTIFICATION: code 3/4 (update: attribute flags error) — 0000 0000 ffff ffff ffff ffff ffff ffff ffff ffff 0020 ( 03 ) 03 04e0 0708 0003 02ed 5bdc 3f01

А следом уже само сообщение и то что мы распознали (раздел 4.5) 03 04 — тип и подтип ошибки: code 3/4 (update: attribute flags error) — 0000 0000 ffff ffff ffff ffff ffff ffff ffff ffff 0020 03 ( 03 04 ) e0 0708 0003 02ed 5bdc 3f01

Ericsson повторил нам не только поле data которое начинается с e0, а всё сформированное сообщение. В логе Cisco именно с него начинается байтовая последовательность. Лог FRRouting, также содержит полностью расшифрованный заголовок BGP сообщения NOTIFICATION за которым следует уже поле data, к декодированию которого мы возвращаемся.

Читайте также:  Fan error lenovo b590 что это

Направляемся к описанию формата UPDATE, так как рассчитываем там найти описание форматов атрибутов, чтобы понять что именно мы всё же получаем. UPDATE содержит много полей, атрибуты задаются в поле переменной длины Path Attributes:

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

Здесь опять надо читать всё подряд, так как всё оформлено сплошным текстом. Из него следует, что поле флагов использует 4 первых бита с 0 по 3, а второй байт определяет сам атрибут. Сведём всё это в таблицу:

Бит Attr. Flags Значение Связанный атрибут
0 – well-known 1 — ORIGIN
2 — AS_PATH
3 — NEXT-HOP
5 — LOCAL_PREF
6 — ATOMIC_AGGREGATE
1 — optional 4 — MULTI_EXIT_DISC
7 — AGGREGATOR
1 0 – optional non-transitive MULTI_EXIT_DISC
1 – optional transitive или для всех well-known ORIGIN
AS-PATH
NEXT-HOP
ATOMIC_AGGREGATE
AGGREGATOR
2 0 — optional complete или для всех well-known и non-transitive ORIGIN
AS-PATH
NEXT-HOP
MULTI_EXIT_DISC
LOCAL_PREF
ATOMIC_AGGREGATE
1 – optional partial

Биты 4-7 должны быть 0 при передаче и игнорироваться при приёме, на них внимание не обращаем. Бит 3 определяет размер поля length в TLV:

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

    В случае, если атрибут не распознаётся этот флаг устанавливается, а сам атрибут передаётся дальше — 9 раздел:

Приступим к разбору UPDATE

Поле флагов в первом случае e0: code 3/4 (update: attribute flags error) — 0000 0000 ffff ffff ffff ffff ffff ffff ffff ffff 0020 0303 04 ( e0 ) 0708 0003 02ed 5bdc 3f01 — в двоичном 1110 0000 — опциональный, транзитивный с установленным флагом partial, поле длины задаётся одним байтом.

code 3/4 (update: attribute flags error) — 0000 0000 ffff ffff ffff ffff ffff ffff ffff ffff 0020 0303 04e0 ( 07 ) 08 0003 02ed 5bdc 3f01 — код атрибута 7 — AGGREGATOR

Размер данных 8 байт: code 3/4 (update: attribute flags error) — 0000 0000 ffff ffff ffff ffff ffff ffff ffff ffff 0020 0303 04e0 07 ( 08 ) 0003 02ed 5bdc 3f01

Во втором случае — общеизвестный атрибут (50 — 0101 0000), размер поля длины в два байта, AS_PATH (02), длина 3294 байта (0c de): 3/5 (UPDATE Message Error/Attribute Length Error) 3298 bytes ( 50 02 0c de ) 02 ff 00 00 0c b9 00 00 00 ae 00 04 00 3e 00 04 00 3e 00 04 00 35 00 04 00 35 . очень много раз 00 04 00 35

Оставшаяся часть строки это поле данных самого атрибута. Для этого продвигаемся дальше по разделу 4.3:

Следует учесть работу с 32-битными ASn RFC6793, чтобы получить следующий результат:

4 байта это AS197357: code 3/4 (update: attribute flags error) — 0000 0000 ffff ffff ffff ffff ffff ffff ffff ffff 0020 0303 04e0 0708 ( 0003 02ed ) 5bdc 3f01 ,

и 4 байта IP адрес 91.220.63.1: code 3/4 (update: attribute flags error) — 0000 0000 ffff ffff ffff ffff ffff ffff ffff ffff 0020 0303 04e0 0708 0003 02ed ( 5bdc 3f01 ) — в сумме 8 байт, как и указано в поле длины.

Во втором случае AS_PATH, сам по себе TLV:

Поля типа и длины размером по 1 байту.

Тип 2, размер данных (ff — 255 ASn): 3/5 (UPDATE Message Error/Attribute Length Error) 3298 bytes 50 02 0c de ( 02 ff ) 00 00 0c b9 00 00 00 ae 00 04 00 3e 00 04 00 3e 00 04 00 35 00 04 00 35 . очень много раз 00 04 00 35

Сами данные — номера AS по 4 байта каждая: 3/5 (UPDATE Message Error/Attribute Length Error) 3298 bytes 50 02 0c de 02 ff ( 00 00 0c b9 ) ( 00 00 00 ae ) ( 00 04 00 3e ) ( 00 04 00 3e ) ( 00 04 00 35 ) ( 00 04 00 35 ) . очень много раз 00 04 00 35 — AS3257, AS174, AS262206 AS262206, AS262197, AS262197, AS262197, AS262197 .

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

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

P.S. В случае FRRouting есть патч, намекающий, что проблема не в формате.

В первом случае, видимо, тоже нужен патч, так как формально я не увидел какой либо проблемы в совместном использовании флагов для атрибута AGGREGATOR, может кто увидел.

Источник

Оцените статью
toolgir.ru
Adblock
detector