Python вывести сообщение exception

Обновлено: 09.05.2024

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

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

Коды статуса против Исключений

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

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

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

Небольшой пример

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

При вызове h() , мы получаем на выходе:

Исключения Python

Python исключениями являются объекты организованные в классовой иерархии.

Вот иерархия целиком:

Существует несколько специальных исключений, которые являются производными от BaseException , такие как SystemExit , KeyboardInterrupt и GeneratorExit . Еще есть класс Exception , который является базовым классом для StopIteration , StandardError и Warning . Все стандартные ошибки являются производными от StandardError .

Вызов исключений

Вызов исключений очень прост. Вы просто используете ключевое слово raise чтобы вызвать объект, который является подклассом Exception . Это может быть экземпляр Exception , одно из стандартных исключений (напр., RuntimeError ), или подкласс Exception , который вы получили. Вот небольшой фрагмент кода, который демонстрирует эти случаи:

Перехват исключений

Вы получили исключение, с условием except , как вы видели в примере. Когда вы получили исключение, у вас есть три варианта:

  • Пропустить (обработать его и продолжить работу).
  • Сделать что-то вроде записи в журнал, но получить повторно то же самое исключение, чтобы продолжить его обработку на более высоком уровне.
  • Вызвать другое исключение вместо текущего.

Пропустить исключение

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

Например, если вы получаете входящий файл, который может быть в различных форматах (JSON, YAML), вы можете попробовать проанализировать его с помощью различных средств. Если анализатор JSON создаёт исключение, которое показывает, что файл имеет некорректный формат JSON, вы пропускаете его и пробуете проанализировать через парсер YAML. Если парсер YAML также не справляется с задачей, тогда вы даёте исключению перейти на следующий уровень.

Обратите внимание, что другие исключения (например, file not found или no read permissions) будут переходить на следующий уровень и не будут обработаны конкретным исключением. Это хорошая тактика в том случае, если вы хотите использовать YAML парсер, когда анализ с помощью JSON парсера не удался.

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

Обратите внимание, что, добавляя as e , вы привязываете объект к имении e в вашем исключении.

Перезапуск исключения

Чтобы перезапустить исключение, просто напишите raise без аргументов внутри обработчика. Это позволит выполнить некоторую локальную обработку, но также пропустит исключение для обработки на верхние уровни. Здесь, функция invoke_function() выводит тип исключения в консоль и затем повторно вызывает его.

Вызов Различных Исключений

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

Финальное утверждение

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

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

Вызов open_db_connection() может не вернуть подключение или вызвать исключение. В этом случае нет необходимости закрывать соединение.

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

Диспетчеров Контекста

Контекстные менеджеры обеспечивают еще один механизм обработки ресурсов, таких как файлы или подключения к БД, которые выполняются автоматически, даже если исключения были вызваны. Вместо блоков try-finally, можно использовать определение with . Вот пример с файлом:

Теперь, даже если process() вызывает исключение, этот файл будет закрыт правильно сразу же когда область видимости блока with завершена, независимо от того, было исключение обработано или нет.

Ведение журнала

Это лучший пример, которую я рекомендую:

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

Sentry

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

Работа с временной ошибкой

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

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

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

Полезные оформители

Два оформителя которые могут помочь в обработке ошибок, это @log_error , который записывает исключение и затем вновь вызывает его и @retry оформитель, который будет повторять вызов функции несколько раз.

Журнал ошибок

Вот пример простой реализации. Оформитель исключает объект logger. Когда он оформляет функцию и функция вызвана, он обработает вызов в блоке try-except, и если там было исключение сделает запись в журнал и наконец повторно вызовет исключение.

Вот пример, как его использовать:

Retrier

Здесь, очень хорошая реализация @retry оформителя.

Заключение

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

Кау вывести в консоль текст ошибки и stacktrace так, как это делается при необработанном исключении:

хочу поймать в try: обработать в except Exception as err:

2 ответа 2

Получить текст трассы стека можно через функцию traceback.format_exc:

Следуя вашим словам, например:


Всё ещё ищете ответ? Посмотрите другие вопросы с метками python python-3.x исключения отладка или задайте свой вопрос.

Похожие

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

дизайн сайта / логотип © 2022 Stack Exchange Inc; материалы пользователей предоставляются на условиях лицензии cc by-sa. rev 2022.2.28.41552

П рограмма, написанная на языке Python, останавливается сразу как обнаружит ошибку. Ошибки могут быть (как минимум) двух типов:

  • Синтаксические ошибки — возникают, когда написанное выражение не соответствует правилам языка (например, написана лишняя скобка);
  • Исключения — возникают во время выполнения программы (например, при делении на ноль).

Как устроен механизм исключений

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

💁‍♂️ Пример : напишем скрипт, в котором функция ожидает число, а мы передаём сроку (это вызовет исключение "TypeError"):

В данном примере мы запускаем файл " test.py " (через консоль). Вызывается функция " a ", внутри которой вызывается функция " b ". Все работает хорошо до сточки print(value + 1) . Тут интерпретатор понимает, что нельзя конкатенировать строку с числом, останавливает выполнение программы и вызывает исключение "TypeError".

Далее ошибка передается по цепочке в обратном направлении: " b " → " a " → " test.py ". Так как в данном примере мы не позаботились обработать эту ошибку, вся информация по ошибке отобразится в консоли в виде Traceback.

Traceback (трассировка) — это отчёт, содержащий вызовы функций, выполненные в определенный момент. Трассировка помогает узнать, что пошло не так и в каком месте это произошло.

Traceback лучше читать снизу вверх ↑

В нашем примере Traceback содержится следующую информацию (читаем снизу вверх):

  1. TypeError — тип ошибки (означает, что операция не может быть выполнена с переменной этого типа);
  2. can only concatenate str (not "int") to str — подробное описание ошибки (конкатенировать можно только строку со строкой);
  3. Стек вызова функций (1-я линия — место, 2-я линия — код). В нашем примере видно, что в файле "test.py" на 11-й линии был вызов функции "a" со строковым аргументом "10". Далее был вызов функции "b". print(value + 1) это последнее, что было выполнено — тут и произошла ошибка.
  4. most recent call last — означает, что самый последний вызов будет отображаться последним в стеке (в нашем примере последним выполнился print(value + 1) ).

В Python ошибку можно перехватить, обработать, и продолжить выполнение программы — для этого используется конструкция try . except . .

Как обрабатывать исключения в Python (try except)

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

Например, вот как можно обработать ошибку деления на ноль:

try: a = 7 / 0 except: print('Ошибка! Деление на 0')

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

try: a = 7 / 0 except ZeroDivisionError: print('Ошибка! Деление на 0')

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

try: a = 7 / 0 except Exception: print('Любая ошибка!')

As — сохраняет ошибку в переменную

Перехваченная ошибка представляет собой объект класса, унаследованного от "BaseException". С помощью ключевого слова as можно записать этот объект в переменную, чтобы обратиться к нему внутри блока except :

try: file = open('ok123.txt', 'r') except FileNotFoundError as e: print(e) > [Errno 2] No such file or directory: 'ok123.txt'

В примере выше мы обращаемся к объекту класса "FileNotFoundError" (при выводе на экран через print отобразится строка с полным описанием ошибки).

У каждого объекта есть поля, к которым можно обращаться (например если нужно логировать ошибку в собственном формате):

import datetime now = datetime.datetime.now().strftime("%d-%m-%Y %H:%M:%S") try: file = open('ok123.txt', 'r') except FileNotFoundError as e: print(f" [FileNotFoundError]: , filename: ") > 20-11-2021 18:42:01 [FileNotFoundError]: No such file or directory, filename: ok123.txt

Finally — выполняется всегда

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

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

В следующем примере откроем файл и обратимся к несуществующей строке:

file = open('ok.txt', 'r') try: lines = file.readlines() print(lines[5]) finally: file.close() if file.closed: print("файл закрыт!") > файл закрыт! > Traceback (most recent call last): > File "test.py", line 5, in > print(lines[5]) > IndexError: list index out of range

Даже после исключения "IndexError", сработал код в секции finally , который закрыл файл.

p.s. данный пример создан для демонстрации, в реальном проекте для работы с файлами лучше использовать менеджер контекста with.

Также можно использовать одновременно три блока try/except/finally . В этом случае:

  • в try — код, который может вызвать исключения;
  • в except — код, который должен выполниться при возникновении исключения;
  • в finally — код, который должен выполниться в любом случае.

Else — выполняется когда исключение не было вызвано

Иногда нужно выполнить определенные действия, когда код внутри блока try не вызвал исключения. Для этого используется блок else .

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

b = int(input('b = ')) c = int(input('c = ')) try: a = b / c except ZeroDivisionError: print('Ошибка! Деление на 0') else: print(f"a = ") > b = 10 > c = 1 > a = 10.0

Несколько блоков except

В программе может возникнуть несколько исключений, например:

  1. Ошибка преобразования введенных значений к типу float ("ValueError");
  2. Деление на ноль ("ZeroDivisionError").

В Python, чтобы по-разному обрабатывать разные типы ошибок, создают несколько блоков except :

try: b = float(input('b = ')) c = float(input('c = ')) a = b / c except ZeroDivisionError: print('Ошибка! Деление на 0') except ValueError: print('Число введено неверно') else: print(f"a = ") > b = 10 > c = 0 > Ошибка! Деление на 0 > b = 10 > c = питон > Число введено неверно

Теперь для разных типов ошибок есть свой обработчик.

Несколько типов исключений в одном блоке except

try: b = float(input('b = ')) c = float(input('c = ')) a = b / c except (ZeroDivisionError, ValueError) as er: print(er) else: print('a = ', a)

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

Raise — самостоятельный вызов исключений

Исключения можно генерировать самостоятельно — для этого нужно запустить оператор raise .

min = 100 if min > 10: raise Exception('min must be less than 10') > Traceback (most recent call last): > File "test.py", line 3, in > raise Exception('min value must be less than 10') > Exception: min must be less than 10

min = 100 try: if min > 10: raise Exception('min must be less than 10') except Exception: print('Моя ошибка') > Моя ошибка

Кроме того, ошибку можно обработать в блоке except и пробросить дальше (вверх по стеку) с помощью raise :

min = 100 try: if min > 10: raise Exception('min must be less than 10') except Exception: print('Моя ошибка') raise > Моя ошибка > Traceback (most recent call last): > File "test.py", line 5, in > raise Exception('min must be less than 10') > Exception: min must be less than 10

Как пропустить ошибку

Иногда ошибку обрабатывать не нужно. В этом случае ее можно пропустить с помощью pass :

try: a = 7 / 0 except ZeroDivisionError: pass

Исключения в lambda функциях

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

20 типов встроенных исключений в Python

Иерархия классов для встроенных исключений в Python выглядит так:

BaseException SystemExit KeyboardInterrupt GeneratorExit Exception ArithmeticError AssertionError . . . ValueError Warning

Все исключения в Python наследуются от базового BaseException :

  • SystemExit — системное исключение, вызываемое функцией sys.exit() во время выхода из приложения;
  • KeyboardInterrupt — возникает при завершении программы пользователем (чаще всего при нажатии клавиш Ctrl+C);
  • GeneratorExit — вызывается методом close объекта generator ;
  • Exception — исключения, которые можно и нужно обрабатывать (предыдущие были системными и их трогать не рекомендуется).

От Exception наследуются:

1 StopIteration — вызывается функцией next в том случае если в итераторе закончились элементы;

2 ArithmeticError — ошибки, возникающие при вычислении, бывают следующие типы:

  • FloatingPointError — ошибки при выполнении вычислений с плавающей точкой (встречаются редко);
  • OverflowError — результат вычислений большой для текущего представления (не появляется при операциях с целыми числами, но может появиться в некоторых других случаях);
  • ZeroDivisionError — возникает при попытке деления на ноль.

3 AssertionError — выражение, используемое в функции assert неверно;

4 AttributeError — у объекта отсутствует нужный атрибут;

5 BufferError — операция, для выполнения которой требуется буфер, не выполнена;

6 EOFError — ошибка чтения из файла;

7 ImportError — ошибка импортирования модуля;

8 LookupError — неверный индекс, делится на два типа:

  • IndexError — индекс выходит за пределы диапазона элементов;
  • KeyError — индекс отсутствует (для словарей, множеств и подобных объектов);

9 MemoryError — память переполнена;

10 NameError — отсутствует переменная с данным именем;

11 OSError — исключения, генерируемые операционной системой:

  • ChildProcessError — ошибки, связанные с выполнением дочернего процесса;
  • ConnectionError — исключения связанные с подключениями (BrokenPipeError, ConnectionResetError, ConnectionRefusedError, ConnectionAbortedError);
  • FileExistsError — возникает при попытке создания уже существующего файла или директории;
  • FileNotFoundError — генерируется при попытке обращения к несуществующему файлу;
  • InterruptedError — возникает в том случае если системный вызов был прерван внешним сигналом;
  • IsADirectoryError — программа обращается к файлу, а это директория;
  • NotADirectoryError — приложение обращается к директории, а это файл;
  • PermissionError — прав доступа недостаточно для выполнения операции;
  • ProcessLookupError — процесс, к которому обращается приложение не запущен или отсутствует;
  • TimeoutError — время ожидания истекло;

12 ReferenceError — попытка доступа к объекту с помощью слабой ссылки, когда объект не существует;

13 RuntimeError — генерируется в случае, когда исключение не может быть классифицировано или не подпадает под любую другую категорию;

14 NotImplementedError — абстрактные методы класса нуждаются в переопределении;

15 SyntaxError — ошибка синтаксиса;

16 SystemError — сигнализирует о внутренне ошибке;

17 TypeError — операция не может быть выполнена с переменной этого типа;

18 ValueError — возникает когда в функцию передается объект правильного типа, но имеющий некорректное значение;

19 UnicodeError — исключение связанное с кодирование текста в unicode , бывает трех видов:

  • UnicodeEncodeError — ошибка кодирования;
  • UnicodeDecodeError — ошибка декодирования;
  • UnicodeTranslateError — ошибка перевода unicode .

20 Warning — предупреждение, некритическая ошибка.

💭 Посмотреть всю цепочку наследования конкретного типа исключения можно с помощью модуля inspect :

import inspect print(inspect.getmro(TimeoutError)) > ( , , , , )

📄 Подробное описание всех классов встроенных исключений в Python смотрите в официальной документации .

Как создать свой тип Exception

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

class MyError(Exception): def __init__(self, text): self.txt = text try: raise MyError('Моя ошибка') except MyError as er: print(er) > Моя ошибка

С помощью try/except контролируются и обрабатываются ошибки в приложении. Это особенно актуально для критически важных частей программы, где любые "падения" недопустимы (или могут привести к негативным последствиям). Например, если программа работает как "демон", падение приведет к полной остановке её работы. Или, например, при временном сбое соединения с базой данных, программа также прервёт своё выполнение (хотя можно было отловить ошибку и попробовать соединиться в БД заново).

Вместе с try/except можно использовать дополнительные блоки. Если использовать все блоки описанные в статье, то код будет выглядеть так:

Подробнее о работе с исключениями в Python можно ознакомиться в официальной документации .


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

Эффективная обработка исключений

Введение

Давайте рассмотрим следующую систему. У нас есть микросервис, который отвечает за:

· Прослушивание событий о новом заказе;

· Получение заказа из базы данных;

· Проверку состояния принтера;

· Отправка квитанции в налоговую систему (IRS).


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

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

И примерно вот такой код на этот случай пишут люди (он, конечно, работает, но плохо и неэффективно):

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

Почему этот сервис — blob?

Этот сервис знает слишком много. Кто-то может сказать, что он знает только то, что ему нужно (то есть все шаги, связанные с формированием чека), но на самом деле он знает куда больше.

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

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

Первое улучшение: делайте исключения конкретными

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

Я выделю только то, что мы поменяли:

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

Второе улучшение: не лезьте не в свое дело

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

Но это еще не все. Логирование продолжает меня раздражать.

Третье улучшение: улучшение логирования

Вот пример вывода ваших логов:

Последнее улучшение: упрощение

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

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

Перейдем к упрощению.

Мы только что создали новый метод ensure_order_unlocked для нашего status_service , который теперь отвечает за создание исключений/логирование в случае, если что-то идет не так.

Хорошо, а теперь скажите, насколько легче теперь стало это читать?

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

Теперь этот код такой же простой, каким (в основном) должен быть любой код.

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

Эффективное создание исключений

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

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

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

Ловим и создаем исключения эффективно

Еще одна вещь, которую люди часто делают неправильно – это отлавливают и повторно создают исключения.

Согласно PEP 3134 Python, делать нужно следующим образом.

Повторное создание исключения

Обычной инструкции raise более чем достаточно.

Создание одного исключения из другого

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

Эффективное логирование исключений

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

Используйте logger.exception

А что, если это не ошибка?

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

Источники

Принципы и качество кода:

Читайте также: