Как получить имя ошибки python

When you say «name» this could mean a couple of things: it could mean only the «immediate» classname, or it could mean the fully qualified name. Usually the latter will be much more useful and less error-prone: I’ve come across more than one case of 2 or more types with same «immediate» classname but from different packages.

If you want to print or log the fully qualified name this is one of the simplest things to do:

try:
    do_something()
except BaseException as e:
    logger.error(f'whoops! {type(e)}: {e}')
    # or maybe
    print(f'whoops! {type(e)}: {e}', file=sys.stderr)

The fully qualified classname will then be printed out like this: «<class ‘json.decoder.JSONDecodeError’>», and then be followed by the exception message. The OP says he wants «for example», to print a message, so assert statements as in the chosen answer don’t seem to be called for.

The answer by MrName is also not irrelevant, and does make a sensible suggestion! if in the above you replaced logger.error(...) with logger.exception('whoops!') (NB a user message is a required param) you’d get your exception’s fully qualified name logged, not to mention its message, and a stack trace for free.

PS as suggested by the name, JSONDecodeError in my example is an Error, not an Exception (it is a subclass of ValueError). Catching BaseException (the superclass of both Error and Exception) usually makes life easier when you’re not fishing for a specific exception. The OP says he wants to catch «all» exceptions.

How to get the name of an exception that was caught in Python

Ссылка на оверфло

Три варианта:

  • type(exception).__name__
  • exception.__class__.__name__
  • exception.__class__.__qualname__

Пример реализации

try:
    foo = bar
except Exception as exception:
    assert type(exception).__name__ == 'NameError'
    assert exception.__class__.__name__ == 'NameError'
    assert exception.__class__.__qualname__ == 'NameError'

Смотри в дополнение про то, как получить сообщение ошибки в виде строки [2021-06-04-daily-note]

Feature Launch: Import scripts into notebook kernels

Скажем так, не сильно полезная фича, т.к. нет возможности выстроить настоящую структуру пакета, а импорт ограничивается ноутом. Ну и плюс все это надо делать руками через jupyter notebook. Но, если есть какие-то сильно часто встречающиеся куски кода, то можно попробовать так реализовать.

  • Create a script kernel with the code you’d like to import.
  • Under the “File” menu, click on “Make Utility Script”. This will let you import this script to notebook kernels.
  • Commit your script. When you import a script, you’re importing the most recent committed version. If you haven’t committed a version yet, you won’t see it in the list of scripts you can import.
  • Open the notebook where you’d like to import the script.
  • Add the script. Under “File”, click “Add utility script”. Search for the script you want and click to add it. You should see it listed under “usr/lib” in the panel on the right hand side.
  • Import your script. In Python you can do this using import nameof_script.
  • Use the functions or objects you’ve imported!

  • a utility script can be a combination of multiple code snippets in different source files
  • be able to add data/non-code related files as part of the utility function
  • allow folder structure where code and data can reside in a structured fashion
  • allow access to the data area of the notebook via an environment variable or some other method
  • allow linking a gist where the code can reside (gist will contain the code for the utility script)
  • allow linking a git repo (via branch or commit points) — will contain the code for the utility script)
  • allow linking only a folder in a git repo where the code and data resides

The above will help in the following ways:

  • keep the main utility script small, simple and modular
  • easy to read, change and use
  • can be version controlled via another public SCM system while still visible to the kernel
  • keep components of the utility script separate from the data or configuration files in an organised manner

Какое-то там обсуждение на эту тему

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

  • факт, что произошла ошибка
  • особенности произошедшей ошибки (ошибка, скрывающая антипаттерн)

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

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

Итак, как поймать общее исключение? Есть несколько способов. Если вы просто хотите объект исключения, сделайте следующее:

try:
    someFunction()
except Exception as ex:
    template = "An exception of type {0} occurred. Arguments:n{1!r}"
    message = template.format(type(ex).__name__, ex.args)
    print message

Удостоверьтесь, что message доведено до сведения пользователя очень трудно! Печатать его, как показано выше, может быть недостаточно, если сообщение захоронено множеством других сообщений. Неспособность привлечь внимание пользователей равносильна проглатыванию всех исключений, и если у вас будет какое-то впечатление, что вам следует уйти после прочтения ответов на этой странице, это не очень хорошо. Завершение блока except с помощью оператора raise устраняет проблему путем прозрачного повторения исключения, которое было обнаружено.

Разница между приведенным выше и использованием только except: без каких-либо аргументов двояка:

  • Голый except: не дает вам объект исключения для проверки
  • Исключения SystemExit, KeyboardInterrupt и GeneratorExit не пойманы указанным выше кодом, что обычно является тем, что вы хотите. См. Иерархию исключений .

Если вы также хотите получить ту же стек, что и вы, если не поймаете исключение, вы можете получить это так (все еще внутри предложения except):

import traceback
print traceback.format_exc()

Если вы используете модуль logging, вы можете распечатать исключение в журнале (вместе с сообщением) следующим образом:

import logging
log = logging.getLogger()
log.exception("Message for you, sir!")

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

import pdb
pdb.post_mortem()

Я нашел этот последний метод бесценным при поиске ошибок.

Цитата
Сообщение от alex925
Посмотреть сообщение

Веди логи и все, можешь сохранять полный traceback в лог.

Я с такой техникой не знаком. Зачем логи в разработке на Питоне?
В разработке мы оперируем срочной информацией. Вот оно упало — посмотрели, организовали обработчик исключений.

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

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

Вот мне в бытность студентом репетитор по Java говорил — чтобы быть продуктивным, кодишь до обеда, компилируешься, кодишь до вечера, компилируешься. Если будешь постоянно компилироваться, то времени на программирование не останется. Но у него-то был компилируемый язык. Т.е. — да, он кодил до обеда, и только потом ловил свои ошибки.

А еще давным давно мужики кодили на бумажке. Потом отдавали оператору. Оператор вбивал на перфокарты. Потом программист ждал освобождения машинного времени. Его перфокарты прогоняли. Он приходил. А там написано: «Ошибка компиляции». И он уходил думать. И думал опять на бумажке, опять наборщик и т.п.

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

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

Но как она может снизиться. Это же не компиляция. А на узнавание исключения в документации Вы все равно время потратите.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

a = 8
b = 10
c = a b
File "", line 3
 c = a b
       ^
SyntaxError: invalid syntax

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

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

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

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

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

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

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

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

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

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

def recursion():
    return recursion()

recursion()
---------------------------------------------------------------------------

RecursionError                            Traceback (most recent call last)

 in 
----> 1 recursion()


 in recursion()
      1 def recursion():
----> 2     return recursion()


... last 1 frames repeated, from the frame below ...


 in recursion()
      1 def recursion():
----> 2     return recursion()


RecursionError: maximum recursion depth exceeded

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

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

Пример:

for i in range(10):
    print('Привет Мир!')
  File "", line 2
    print('Привет Мир!')
        ^
IndentationError: expected an indented block

Исключения

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

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

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

a = 2
b = 'PythonRu'
a + b
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

 in 
      1 a = 2
      2 b = 'PythonRu'
----> 3 a + b


TypeError: unsupported operand type(s) for +: 'int' and 'str'

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

10 / 0
---------------------------------------------------------------------------

ZeroDivisionError                         Traceback (most recent call last)

 in 
----> 1 10 / 0


ZeroDivisionError: division by zero

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

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

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

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

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

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

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

try:
    inp = input()
    print('Нажмите Ctrl+C и прервите Kernel:')
except KeyboardInterrupt:
    print('Исключение KeyboardInterrupt')
else:
    print('Исключений не произошло')

Исключение KeyboardInterrupt

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

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

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

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

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

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

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

try:  
    a = 100 / 0
    print(a)
except ZeroDivisionError:  
    print("Исключение ZeroDivisionError." )
else:  
    print("Успех, нет ошибок!")
Исключение ZeroDivisionError.

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

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

try:  
    import math
    print(math.exp(1000))
except OverflowError:  
    print("Исключение OverFlow.")
else:  
    print("Успех, нет ошибок!")
Исключение OverFlow.

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

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

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

try:  
    a = 100
    b = "PythonRu"
    assert a == b
except AssertionError:  
    print("Исключение AssertionError.")
else:  
    print("Успех, нет ошибок!")

Исключение AssertionError.

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

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

class Attributes(obj):
    a = 2
    print(a)

try:
    obj = Attributes()
    print(obj.attribute)
except AttributeError:
    print("Исключение AttributeError.")

2
Исключение AttributeError.

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

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

import nibabel
---------------------------------------------------------------------------

ModuleNotFoundError                       Traceback (most recent call last)

 in 
----> 1 import nibabel


ModuleNotFoundError: No module named 'nibabel'

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

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

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

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

Ошибка ключа

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

try:  
    a = {1:'a', 2:'b', 3:'c'}  
    print(a[4])  
except LookupError:  
    print("Исключение KeyError.")
else:  
    print("Успех, нет ошибок!")

Исключение KeyError.

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

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

try:
    a = ['a', 'b', 'c']  
    print(a[4])  
except LookupError:  
    print("Исключение IndexError, индекс списка вне диапазона.")
else:  
    print("Успех, нет ошибок!")
Исключение IndexError, индекс списка вне диапазона.

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

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

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

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

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

try:
    print(ans)
except NameError:  
    print("NameError: переменная 'ans' не определена")
else:  
    print("Успех, нет ошибок!")
NameError: переменная 'ans' не определена

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

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

class BaseClass(object):
    """Опередляем класс"""
    def __init__(self):
        super(BaseClass, self).__init__()
    def do_something(self):
	# функция ничего не делает
        raise NotImplementedError(self.__class__.__name__ + '.do_something')

class SubClass(BaseClass):
    """Реализует функцию"""
    def do_something(self):
        # действительно что-то делает
        print(self.__class__.__name__ + ' что-то делает!')

SubClass().do_something()
BaseClass().do_something()

SubClass что-то делает!



---------------------------------------------------------------------------

NotImplementedError                       Traceback (most recent call last)

 in 
     14
     15 SubClass().do_something()
---> 16 BaseClass().do_something()


 in do_something(self)
      5     def do_something(self):
      6         # функция ничего не делает
----> 7         raise NotImplementedError(self.__class__.__name__ + '.do_something')
      8
      9 class SubClass(BaseClass):


NotImplementedError: BaseClass.do_something

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

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

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

try:
    a = 5
    b = "PythonRu"
    c = a + b
except TypeError:
    print('Исключение TypeError')
else:
    print('Успех, нет ошибок!')

Исключение TypeError

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

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

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

try:
    print(float('PythonRu'))
except ValueError:
    print('ValueError: не удалось преобразовать строку в float: 'PythonRu'')
else:
    print('Успех, нет ошибок!')
ValueError: не удалось преобразовать строку в float: 'PythonRu'

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

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

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

class UnAcceptedValueError(Exception):   
    def __init__(self, data):    
        self.data = data
    def __str__(self):
        return repr(self.data)

Total_Marks = int(input("Введите общее количество баллов: "))
try:
    Num_of_Sections = int(input("Введите количество разделов: "))
    if(Num_of_Sections < 1):
        raise UnAcceptedValueError("Количество секций не может быть меньше 1")
except UnAcceptedValueError as e:
    print("Полученная ошибка:", e.data)

Введите общее количество баллов: 10
Введите количество разделов: 0
Полученная ошибка: Количество секций не может быть меньше 1

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

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

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

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

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

import timeit
setup="a=0"
stmt1 = '''
try:
    b=10/a
except ZeroDivisionError:
    pass'''

stmt2 = '''
if a!=0:
    b=10/a'''

print("time=",timeit.timeit(stmt1,setup,number=10000))
print("time=",timeit.timeit(stmt2,setup,number=10000))

time= 0.003897680000136461
time= 0.0002797570000439009

Выводы!

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

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

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

In this article, let us learn about printing error messages from Exceptions with the help of 5 specifically chosen examples.

I have divided this article into 2 major sections

  1. Printing custom error messages and
  2. Printing a specific part of the default error message. By “default error message“, I mean the error message that you typically get in the command line if you did not catch a given exception)

Depending on which of the 2 options above you are looking for, you can jump to the respective section of the article using the table of content below.

So, let’s begin!

Printing Custom Error messages

There are 3 ways to print custom error messages in Python. Let us start with the simplest of the 3, which is using a print() statement.

Option#1: Using a simple print() statement

The first and easiest option is to print error messages using a simple print() statement as shown in the example below.

try:
    #Some Problematic code that can produce Exceptions
    x = 5/0
except Exception as e:
  print('A problem has occurred from the Problematic code: ', e)

Running this code will give the output below.

A problem has occurred from the Problematic code: division by zero

Here the line “x = 5/0″ in Example 1 above raised a “ZeroDivisionError” which was caught by our except clause and the print() statement printed the default error message which is “division by zero” to the standard output.

One thing to note here is the line “except Exception as e“. This line of code’s function is to catch all possible exceptions, whichever occurs first as an “Exception” object. This object is stored in the variable “e” (line 4), which returns the string ‘division by zero‘ when used with the print() statement (line 5).

To summarize if you wish to print out the default error message along with a custom message use Option#1.

This is the simplest way to print error messages in python. But this option of putting your custom messages into print statements might not work in cases where you might be handling a list of exceptions using a single except clause. If you are not exactly sure how to catch a list of exceptions using a single except clause, I suggest reading my other article in the link below.

Python: 3 Ways to Catch Multiple Exceptions in a single “except” clause

There I have explained the 3 ways through which you can catch a list of exceptions along with tips on when is the right situation to catch each of these exceptions.

Now that we have learned how to print the default string which comes with an exception object, let us next learn how to customize the message that e carried (the string ‘division by zero‘) and replace that with our own custom error message.

Option#2: Using Custom Exception classes to get customized error messages

In Python, you can define your own custom exception classes by inheriting from another Exception class as shown in the code below.

class MyOwnException(Exception):
    def __str__(self):
        return 'My Own Exception has occurred'

    def __repr__(self):
        return str(type(self))
try:
    raise MyOwnException
except MyOwnException as e:
    print(e)
    print(repr(e))

How to choose the exception class to inherit from?

In the above example, I have inherited from the Exception class in python, but the recommended practice is to choose a class that closely resembles your use-case.

For example, say you are trying to work with a string type object and you are given a list type object instead, here you should inherit your custom exception from TypeError since this Exception type closely resembles your use case which is “the variable is not of expected type”.

If you are looking for getting an appropriate Exception class to inherit from, I recommend having a look at all the built-in exceptions from the official python page here. For the sake of keeping this example simple, I have chosen the higher-level exception type named “Exception” class to inherit from.

In the code below, we are collecting values from the user and to tell the user that there is an error in the value entered we are using the ValueError class.

class EnteredGarbageError(ValueError):
    def __str__(self):
        return 'You did not select an option provided!'    

try:
    options = ['A', 'B', 'C']
    x = input('Type A or B or C: ')
    if x not in options:
        raise EnteredGarbageError
    else:
        print ('You have chosen: ', x)

except EnteredGarbageError as err:
    print(err)

Now that we understand how to choose a class to inherit from, let us next have a look at how to customize the default error messages that these classes return.

How to customize the error message in our custom exception class?

To help us achieve our purpose here which is to print some custom error messages, all objects in python come with 2 methods named __str__ and __repr__. This is pronounced “dunder-str” and “dunder-repr” where “dunder” is short for “double underscore”.

Dunder-str method:

The method __str__ returns a string and this is what the built-in print() function calls whenever we pass it an object to print.

print(object1)

In the line above, python will call the __str__ method of the object and prints out the string returned by that method.

Let us have a look at what python’s official documentation over at python.org has to say about the str method.

https://docs.python.org/3/reference/datamodel.html#object.str

In simpler words, the str method returns a human-readable string for logging purposes, and when this information is passed to the built-in function print(), the string it returns gets printed.

So since our implementation of str returns the string “My Own Exception has occurred” this string got printed on the first line of the exception message.

Dunder-repr method:

__repr__ is another method available in all objects in python.

Where it differs from the dunder-str method is the fact that while the __str__ is used for getting a “friendly message”, the __repr__ method is used for getting, a more of a, “formal message”. You can think of str as a text you got from your friends and repr as a notice you got from a legal representative!

The below screenshot from python’s official documentation explains the use of __repr__ method.

https://docs.python.org/3/reference/datamodel.html#object.repr

Again, in simpler words, repr is typically used to print some “formal” or “official” information about an object in Python

In our Example 2 above, the repr method returned the class name using the built-in type() function.

Next, let us see another variation where we can print different error messages using a single Exception class without making a custom class.

Option#3: Custom Error messages from the raise statement

try:
  raise Exception('I wish to print this message')
except Exception as error:
  print(error)

Lucky for us, python has made this process incredibly simple! Just pass in the message as an argument to the type of exception you wish to raise and this will print that custom message instead!

In the above code, we are throwing an exception of type “Exception” by calling its constructor and giving the custom message as an argument, which then overrides the default __str__ method to return the string passed in.

If you wish to learn more about raise statement, I suggest reading my other article in the link below
Python: Manually throw/raise an Exception using the “raise” statement

where I have explained 3 ways you can use the raise statement in python and when to use each.

But when to use option 2 and when to use option 3?

On the surface, Option#3 of passing in the custom message may look like it made option#2 of using custom classes useless. But the main reason to use Option#2 is the fact that Option#2 can be used to override more than just the __str__ method.

Let’s next move on to section 2 of this article and look at how to choose a specific part of the default error message (the error printed on the console when you don’t catch an exception) and use that to make our own error messages

Choosing Parts of Default Error Messages to print

To understand what I mean by “Default Error Message” let us see an example

raise ValueError("This is an ValueError")

This line when run, will print the following error message

Traceback (most recent call last):

  File "<ipython-input-24-57127e33a735>", line 1, in <module>
    raise ValueError("This is an ValueError")

ValueError: This is an ValueError

This error message contains 3 Parts

  • Exception Type (ValueError)
  • Error message (This is an ValueError)
  • and the stack trace (the 1st few lines showing us where exactly in the program the exception has occurred)

The information needed

  • to extract and use each of the individual pieces of information listed above and
  • when to use what piece of information

is already covered with the help of several examples in my previous article in the link below

Python Exceptions: Getting and Handling Error Messages as strings.

And with that I will end this article!

If you are looking for another interesting read, try the article in the link below.

Exceptions in Python: Everything You Need To Know!

The above article covers all the basics of Exception handling in Python like

  • when and how to ignore exceptions
  • when and how to retry the problematic code that produced the exception and
  • when and how to log the errors

I hope you enjoyed reading this article and got some value from it.

Feel free to share it with your friends and colleagues!



у меня есть функция, вызываемая из основной программы:

try:
someFunction()
except:
print "exception happened!"

но в середине выполнения функции он вызывает исключение, поэтому он переходит к except часть.

как я могу точно видеть, что произошло в someFunction(), которая вызвала исключение произойдет?


1314  


12  

12 ответов:

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

  • то, что произошла ошибка
  • особенности ошибки, которая произошла (ошибка сокрытия антипаттерна)

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

  • представить исключения в виде диалогов в графическом интерфейсе
  • перенос исключений из рабочего потока или процесса в управляющий поток или процесс в многопоточном или многопроцессорном приложении

Итак, как поймать общее исключение? Есть несколько способов. Если вы просто хотите объект исключения, сделайте это так:

try:
    someFunction()
except Exception as ex:
    template = "An exception of type {0} occurred. Arguments:n{1!r}"
    message = template.format(type(ex).__name__, ex.args)
    print message

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

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

  • голой except: не дает вам объект исключения для проверки
  • исключения SystemExit,KeyboardInterrupt и GeneratorExit не пойман выше код, который, как правило, то, что вы хотите. Смотрите иерархия исключений.

если вы также хотите получить тот же stacktrace, если вы не поймаете исключение, вы можете получить это так (все еще внутри предложения except):

import traceback
print traceback.format_exc()

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

import logging
log = logging.getLogger()
log.exception("Message for you, sir!")

если вы хотите копнуть глубже и изучить стек, посмотрите на переменные и т. д. используйте post_mortem функция pdb модуль внутри блока except:

import pdb
pdb.post_mortem()

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

получить имя класса, которому принадлежит объект исключения:

e.__class__.__name__

и с помощью функции print_exc () также будет печатать трассировку стека, которая является важной информацией для любого сообщения об ошибке.

такой:

from traceback import print_exc

class CustomException(Exception): pass

try:
    raise CustomException("hi")
except Exception, e:
    print 'type is:', e.__class__.__name__
    print_exc()
    # print "exception happened!"

вы получите такой вывод:

type is: CustomException
Traceback (most recent call last):
  File "exc.py", line 7, in <module>
    raise CustomException("hi")
CustomException: hi

и после печати и анализа код может решить не обрабатывать исключение и просто выполнить raise:

from traceback import print_exc

class CustomException(Exception): pass

def calculate():
    raise CustomException("hi")

try:
    calculate()
except Exception, e:
    if e.__class__ == CustomException:
        print 'special case of', e.__class__.__name__, 'not interfering'
        raise
    print "handling exception"

выход:

special case of CustomException not interfering

и интерпретатор печатает исключение:

Traceback (most recent call last):
  File "test.py", line 9, in <module>
    calculate()
  File "test.py", line 6, in calculate
    raise CustomException("hi")
__main__.CustomException: hi

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

from traceback import print_exc

class CustomException(Exception): pass

def calculate():
    raise CustomException("hi")

try:
    calculate()
except Exception, e:
    if e.__class__ == CustomException:
        print 'special case of', e.__class__.__name__, 'not interfering'
        #raise CustomException(e.message)
        raise e
    print "handling exception"

выход:

special case of CustomException not interfering
Traceback (most recent call last):
  File "test.py", line 13, in <module>
    raise CustomException(e.message)
__main__.CustomException: hi    

обратите внимание, что трассировка не включает

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

try:
    ...
except Exception as ex:
    print ex # do whatever you want for debugging.
    raise    # re-raise exception.

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

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

try:
    someFunction()
except ValueError:
    # do something
except ZeroDivision:
    # do something else

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

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

попробовать:
someFunction()
кроме исключения, искл:

#this is how you get the type
excType = exc.__class__.__name__

#here we are printing out information about the Exception
print 'exception type', excType
print 'exception msg', str(exc)

#It's easy to reraise an exception with more information added to it
msg = 'there was a problem with someFunction'
raise Exception(msg + 'because of %s: %s' % (excType, exc))

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

path = 'app.p'

def load():
    if os.path.exists(path):
        try:
            with open(path, 'rb') as file:
                data = file.read()
                inst = pickle.load(data)
        except Exception as e:
            inst = solve(e, 'load app data', easy=lambda: App(), path=path)()
    else:
        inst = App()
    inst.loadWidgets()

# e.g. A solver could search for app data if desc='load app data'
def solve(e, during, easy, **kwargs):
    class_name = e.__class__.__name__
    print(class_name + ': ' + str(e))
    print('t during: ' + during)
    return easy

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

в приведенном примере одним из решений может быть поиск данных приложения, хранящихся где-то еще, скажем, если » приложение.P ‘ файл был удален по ошибке.

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

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

class general_function_handler(object):
    def __init__(self, func):
        self.func = func
    def __get__(self, obj, type=None):
        return self.__class__(self.func.__get__(obj, type))
    def __call__(self, *args, **kwargs):
        try:
            retval = self.func(*args, **kwargs)
        except Exception, e :
            logging.warning('Exception in %s' % self.func)
            template = "An exception of type {0} occured. Arguments:n{1!r}"
            message = template.format(type(e).__name__, e.args)
            logging.exception(message)
            sys.exit(1) # exit on all exceptions for now
        return retval

Это может быть вызвано на метод класса или автономную функцию с декоратором:

@general_function_handler

смотрите мой блог о полном примере: http://ryaneirwin.wordpress.com/2014/05/31/python-decorators-and-exception-handling/

вы можете начать, как рекомендовал Лауриц, с:

except Exception as ex:

и просто print ex вот так:

try:
    #your try code here
except Exception as ex:
    print ex

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

try:
    i = 1/0
except Exception as e:
    print e

вы можете узнать больше об исключениях из Учебник По Python.

Ваш вопрос: «Как я могу точно увидеть, что произошло в someFunction (), что вызвало исключение?»

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

самый простой способ-использовать отладчик, который может остановиться там, где происходит неперехваченное исключение, предпочтительно не выходя, так что вы можете проверьте переменные. Например, PyDev в Eclipse open source IDE может это сделать. Чтобы включить это в Eclipse, откройте перспективу отладки, выберите Manage Python Exception Breakpoints на и чека Suspend on uncaught exceptions.

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

If a python code throws an exception, we can catch it and print the type, the error message, traceback and get information like file name and line number in python script where the exception occurred.

We can find the type, value, traceback parameters of the error

Type gives the type of exception that has occurred; value contains error message; traceback contains stack snapshot and many other information details about the error message.

The sys.exc_info() function returns a tuple of these three attributes, and the raise statement has a three-argument form accepting these three parts.

Getting exception type, file number and line number in sample code

import sys, os
try:
raise NotImplementedError("No error")
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print(exc_type, fname, exc_tb.tb_lineno

Понравилась статья? Поделить с друзьями:
  • Как посмотреть ошибки на киа рио
  • Как получить 502 ошибку
  • Как посмотреть ошибки на бортовом компьютере штат
  • Как получить 500 ошибку
  • Как посмотреть ошибки вордпресс