Получить описание ошибки python

One has pretty much control on which information from the traceback to be displayed/logged when catching exceptions.

The code

with open("not_existing_file.txt", 'r') as text:
    pass

would produce the following traceback:

Traceback (most recent call last):
  File "exception_checks.py", line 19, in <module>
    with open("not_existing_file.txt", 'r') as text:
FileNotFoundError: [Errno 2] No such file or directory: 'not_existing_file.txt'

Print/Log the full traceback

As others already mentioned, you can catch the whole traceback by using the traceback module:

import traceback
try:
    with open("not_existing_file.txt", 'r') as text:
        pass
except Exception as exception:
    traceback.print_exc()

This will produce the following output:

Traceback (most recent call last):
  File "exception_checks.py", line 19, in <module>
    with open("not_existing_file.txt", 'r') as text:
FileNotFoundError: [Errno 2] No such file or directory: 'not_existing_file.txt'

You can achieve the same by using logging:

try:
    with open("not_existing_file.txt", 'r') as text:
        pass
except Exception as exception:
    logger.error(exception, exc_info=True)

Output:

__main__: 2020-05-27 12:10:47-ERROR- [Errno 2] No such file or directory: 'not_existing_file.txt'
Traceback (most recent call last):
  File "exception_checks.py", line 27, in <module>
    with open("not_existing_file.txt", 'r') as text:
FileNotFoundError: [Errno 2] No such file or directory: 'not_existing_file.txt'

Print/log error name/message only

You might not be interested in the whole traceback, but only in the most important information, such as Exception name and Exception message, use:

try:
    with open("not_existing_file.txt", 'r') as text:
        pass
except Exception as exception:
    print("Exception: {}".format(type(exception).__name__))
    print("Exception message: {}".format(exception))

Output:

Exception: FileNotFoundError
Exception message: [Errno 2] No such file or directory: 'not_existing_file.txt'

Python Print Exception – How to Try-Except-Print an Error

Every programming language has its way of handling exceptions and errors, and Python is no exception.

Python comes with a built-in try…except syntax with which you can handle errors and stop them from interrupting the running of your program.

In this article, you’ll learn how to use that try…except syntax to handle exceptions in your code so they don’t stop your program from running.

What We’ll Cover

  • What is an Exception?
  • The try…except Syntax
  • How to Handle Exceptions with try…except
  • How to Print an Exception with try…except
  • How to Print the Exception Name
  • Conclusion

What is an Exception?

In Python, an exception is an error object. It is an error that occurs during the execution of your program and stops it from running – subsequently displaying an error message.

When an exception occurs, Python creates an exception object which contains the type of the error and the line it affects.

Python has many built-in exceptions such as IndexError, NameError, TypeError, ValueError, ZeroDivisionError KeyError, and many more.

The try…except Syntax

Instead of allowing these exceptions to stop your program from running, you can put the code you want to run in a try block and handle the exception in the except block.

The basic syntax of try…except looks like this:

try:
  # code to run
except:
  # handle error

How to Handle Exceptions with try…except

You can handle each of the exceptions mentioned in this article with try…except. In fact, you can handle all the exceptions in Python with try…except.

For example, if you have a large program and you don’t know whether an identifier exists or not, you can execute what you want to do with the identifier in a try block and handle a possible error in the except block:

try:
  print("Here's variable x:", x)
except:
  print("An error occured") # An error occured

You can see that the except ran because there’s no variable called x in the code.

Keep reading. Because I will show you how to make those errors look better by showing you how to handle exceptions gracefully.

But what if you want to print the exact exception that occurred? You can do this by assigning the Exception to a variable right in front of the except keyword.

When you do this and print the Exception to the terminal, it is the value of the Exception that you get.

This is how I printed the ZeroDivisionError exception to the terminal:

try:
    res = 190 / 0
except Exception as error:
    # handle the exception
    print("An exception occurred:", error) # An exception occurred: division by zero

And this is how I printed the NameError exception too:

try:
  print("Here's variable x:", x)
except Exception as error:
  print("An error occurred:", error) # An error occurred: name 'x' is not defined

You can follow this pattern to print any exception to the terminal.

How to Print the Exception Name

What if you want to get the exact exception name and print it to the terminal? That’s possible too. All you need to do is use the type() function to get the type of the exception and then use the __name__ attribute to get the name of the exception.

This is how I modified the ZeroDivisionError example to print the exact exception:

try:
    res = 190 / 0
except Exception as error:
    # handle the exception
    print("An exception occurred:", type(error).__name__) # An exception occurred: ZeroDivisionError

And this is how I modified the other example to print the NameError example:

try:
  print("Here's variable x:", x)
except Exception as error:
  print("An error occurred:", type(error).__name__) # An error occurred: NameError

Normally, when you encounter an Exception such as NameError and ZeroDivisionError, for example, you get the error in the terminal this way:

Screenshot-2023-03-13-at-17.58.33

Screenshot-2023-03-13-at-17.58.54

You can combine the type() function and that error variable to make the exception look better:

try:
  print("Here's variable x:", x)
except Exception as error:
  print("An error occurred:", type(error).__name__, "–", error) # An error occurred: NameError – name 'x' is not defined
try:
    res = 190 / 0
except Exception as error:
    # handle the exception
    print("An exception occurred:", type(error).__name__, "–", error) # An exception occurred: ZeroDivisionError – division by zero
    

Conclusion

As shown in this article, the try…except syntax is a great way to handle errors and prevent your program from stopping during execution.

You can even print that Exception to the terminal by assigning the error to a variable, and get the exact type of the Exception with the type() function.

Happy coding!



Learn to code for free. freeCodeCamp’s open source curriculum has helped more than 40,000 people get jobs as developers. Get started

Содержание:развернуть

  • Как устроен механизм исключений
  • Как обрабатывать исключения в Python (try except)
  • As — сохраняет ошибку в переменную

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

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

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

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

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

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

  • Исключения в lambda функциях
  • 20 типов встроенных исключений в Python
  • Как создать свой тип Exception

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

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

Синтаксические ошибки исправить просто (если вы используете IDE, он их подсветит). А вот с исключениями всё немного сложнее — не всегда при написании программы можно сказать возникнет или нет в данном месте исключение. Чтобы приложение продолжило работу при возникновении проблем, такие ошибки нужно перехватывать и обрабатывать с помощью блока try/except.

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

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

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

def b(value):
print("-> b")
print(value + 1) # ошибка тут

def a(value):
print("-> a")
b(value)

a("10")

> -> a
> -> b
> Traceback (most recent call last):
> File "test.py", line 11, in <module>
> a("10")
> File "test.py", line 8, in a
> b(value)
> File "test.py", line 3, in b
> print(value + 1)
> TypeError: can only concatenate str (not "int") to str

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

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

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

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

Пример Traceback в Python

В нашем примере 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')

Здесь в блоке try находится код a = 7 / 0 — при попытке его выполнить возникнет исключение и выполнится код в блоке except (то есть будет выведено сообщение «Ошибка! Деление на 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"{now} [FileNotFoundError]: {e.strerror}, filename: {e.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 <module>
> print(lines[5])
> IndexError: list index out of range

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

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

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

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

def sum(a, b):
res = 0

try:
res = a + b
except TypeError:
res = int(a) + int(b)
finally:
print(f"a = {a}, b = {b}, res = {res}")

sum(1, "2")

> a = 1, b = 2, res = 3

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

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

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

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

> b = 10
> c = 1
> a = 10.0

В этом случае, если пользователь присвоит переменной «с» ноль, то появится исключение и будет выведено сообщение «‘Ошибка! Деление на 0′», а код внутри блока else выполняться не будет. Если ошибки не будет, то на экране появятся результаты деления.

Несколько блоков 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 = {a}")

> b = 10
> c = 0
> Ошибка! Деление на 0

> b = 10
> c = питон
> Число введено неверно

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

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

Можно также обрабатывать в одном блоке except сразу несколько исключений. Для этого они записываются в круглых скобках, через запятую сразу после ключевого слова except. Чтобы обработать сообщения «ZeroDivisionError» и «ValueError» в одном блоке записываем их следующим образом:

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 <module>
> 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 <module>
> 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))

> (<class 'TimeoutError'>, <class 'OSError'>, <class 'Exception'>, <class 'BaseException'>, <class 'object'>)

📄 Подробное описание всех классов встроенных исключений в 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 можно использовать дополнительные блоки. Если использовать все блоки описанные в статье, то код будет выглядеть так:

try:
# попробуем что-то сделать
except (ZeroDivisionError, ValueError) as e:
# обрабатываем исключения типа ZeroDivisionError или ValueError
except Exception as e:
# исключение не ZeroDivisionError и не ValueError
# поэтому обрабатываем исключение общего типа (унаследованное от Exception)
# сюда не сходят исключения типа GeneratorExit, KeyboardInterrupt, SystemExit
else:
# этот блок выполняется, если нет исключений
# если в этом блоке сделать return, он не будет вызван, пока не выполнился блок finally
finally:
# этот блок выполняется всегда, даже если нет исключений else будет проигнорирован
# если в этом блоке сделать return, то return в блоке

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

In this Python Tutorial let us learn about the 3 different pieces of information that you can extract and use from the Exceptions caught on your except clauses, and see the best ways to use each of these pieces in our Python programs.

Let us start by learning what the 3 pieces of information are.

What kind of information can you get from Exceptions?

You can get the following 3 pieces of data from exceptions

  • Exception Type,
  • Exception Value a.k.a Error Message, and
  • Stack-trace or Traceback Object.

All three of the above information is printed out by the Python Interpreter when our program crashes due to an exception as shown in the following example

>> my_list = [1,2]
>> print (my_list[3])
Traceback (most recent call last):

  File "<ipython-input-35-63c7f9106be5>", line 1, in <module>
    print (my_list[3])

IndexError: list index out of range

Lines 3,4,5,6 shows the Stack-trace
Line 7 shows the Exception type and Error Message.

Our focus in this article is to learn how to extract the above 3 pieces individually in our except clauses and print them out as needed.

Hence, the rest of the article is all about answering the following questions

  • what does each of the information in the above list mean,
  • how to extract each of these 3 pieces individually and
  • how to use these pieces in our programs.

Piece#1: Printing Exception Type

The Exception Type refers to the class to which the Exception that you have just caught belongs to.

Extracting Piece#1 (Exception Type)

Let us improve our Example 1 above by putting the problematic code into try and except clauses.

try:
  my_list = [1,2]
  print (my_list[3])
except Exception as e:
  print(type(e))

Here, in the try clause, we have declared a List named my_list and initialized the list with 2 items. Then we have tried to print the 3rd/non-existent item in the list.

The except clause catches the IndexError exception and prints out Exception type.

On running the code, we will get the following output

<class 'IndexError'>

As you can see we just extracted and printed out the information about the class to which the exception that we have just caught belongs to!

But how exactly did we do that?
If you have a look at the except clause. In the line

except Exception as e:

what we have done is, we have assigned the caught exception to an object named “e”. Then by using the built-in python function type(), we have printed out the class name that the object e belongs to.

print(type(e))

Where to get more details about Exception Types

Now that we have the “Exception Type”, next we will probably need to get some information about that particular type so that we can get a better understanding of why our code has failed. In order to do that, the best place to start is the official documentation.

For built in exceptions you can have a look at the Python Documentation

For Exception types that come with the libraries that you use with your code, refer to the documentation of your library.

Piece#2: Printing Exception Value a.k.a Error message

The Exception type is definitely useful for debugging, but, a message like IndexError might sound cryptic and a good understandable error-message will make our job of debugging easier without having to look at the documentation.

In other words, if your program is to be run on the command line and you wish to log why the program just crashed then it is better to use an “Error message” rather than an “Exception Type”.

The example below shows how to print such an Error message.

try:
  my_list = [1,2]
  print (my_list[3])
except Exception as e:
  print(e)

This will print the default error message as follows

list index out of range

Each Exception type comes with its own error message. This can be retrieved using the built-in function print().

Say your program is going to be run by a not-so-tech-savvy user, in that case, you might want to print something friendlier. You can do so by passing in the string to be printed along with the constructor as follows.

try:
  raise IndexError('Custom message about IndexError')
except Exception as e:
  print(e)

This will print

Custom message about IndexError

To understand how the built-in function print() does this magic, and see some more examples of manipulating these error messages, I recommend reading my other article in the link below.

Python Exception Tutorial: Printing Error Messages (5 Examples!)

If you wish to print both the Error message and the Exception type, which I recommend, you can do so like below.

try:
  my_list = [1,2]
  print (my_list[3])
except Exception as e:
  print(repr(e))

This will print something like

IndexError('list index out of range')

Now that we have understood how to get control over the usage of Pieces 1 and 2, let us go ahead and look at the last and most important piece for debugging, the stack-trace which tells us where exactly in our program have the Exception occurred.

Piece#3: Printing/Logging the stack-trace using the traceback object

Stack-trace in Python is packed into an object named traceback object.

This is an interesting one as the traceback class in Python comes with several useful methods to exercise complete control over what is printed.

Let us see how to use these options using some examples!

import traceback

try:
  my_list = [1,2]
  print (my_list[3])
except Exception:
  traceback.print_exc()

This will print something like

Traceback (most recent call last):
  File "<ipython-input-38-f9a1ee2cf77a>", line 5, in <module>
    print (my_list[3])
IndexError: list index out of range

which contains the entire error messages printed by the Python interpreter if we fail to handle the exception.

Here, instead of crashing the program, we have printed this entire message using our exception handler with the help of the print_exc() method of the traceback class.

The above Example-6 is too simple, as, in the real-world, we will normally have several nested function calls which will result in a deeper stack. Let us see an example of how to control the output in such situations.

def func3():
  my_list = [1,2]
  print (my_list[3])

def func2():
  print('calling func3')
  func3()

def func1():
  print('calling func2')
  func2()

try:
  print('calling func1')
  func1()
except Exception as e:
    traceback.print_exc()

Here in the try clause we call func1(), which in-turn calls func2(), which in-turn calls func3(), which produces an IndexError. Running the code above we get the following output

calling func1
calling func2
calling func3
Traceback (most recent call last):
  File "<ipython-input-42-2267707e164f>", line 15, in <module>
    func1()
  File "<ipython-input-42-2267707e164f>", line 11, in func1
    func2()
  File "<ipython-input-42-2267707e164f>", line 7, in func2
    func3()
  File "<ipython-input-42-2267707e164f>", line 3, in func3
    print (my_list[3])
IndexError: list index out of range

Say we are not interested in some of the above information. Say we just want to print out the Traceback and skip the error message and Exception type (the last line above), then we can modify the code like shown below.

def func3():
  my_list = [1,2]
  print (my_list[3])

def func2():
  func3()

def func1():
  func2()

try:
  func1()
except Exception as e:
    traceback_lines = traceback.format_exc().splitlines()
    for line in traceback_lines:
      if line != traceback_lines[-1]:
        print(line)

Here we have used the format_exc() method available in the traceback class to get the traceback information as a string and used splitlines() method to transform the string into a list of lines and stored that in a list object named traceback_lines

Then with the help of a simple for loop we have skipped printing the last line with index of -1 to get an output like below

Traceback (most recent call last):
  File "<ipython-input-43-aff649563444>", line 3, in <module>
    func1()
  File "<ipython-input-42-2267707e164f>", line 11, in func1
    func2()
  File "<ipython-input-42-2267707e164f>", line 7, in func2
    func3()
  File "<ipython-input-42-2267707e164f>", line 3, in func3
    print (my_list[3])

Another interesting variant of formatting the information in the traceback object is to control the depth of stack that is actually printed out.

If your program uses lots of external library code, odds are the stack will get very deep, and printing out each and every level of function call might not be very useful. If you ever find yourself in such a situation you can set the limit argument in the print_exc() method like shown below.

traceback.print_exc(limit=2, file=sys.stdout)

This will limit the number of levels to 2. Let us use this line of code in our Example and see how that behaves

def func3():
  my_list = [1,2]
  print (my_list[3])

def func2():
  func3()

def func1():
  func2()

try:
  func1()
except Exception as e:
  traceback.print_exc(limit=2)

This will print

Traceback (most recent call last):
  File "<ipython-input-44-496132ff4faa>", line 12, in <module>
    func1()
  File "<ipython-input-44-496132ff4faa>", line 9, in func1
    func2()
IndexError: list index out of range

As you can see, we have printed only 2 levels of the stack and skipped the 3rd one, just as we wanted!

You can do more things with traceback like formatting the output to suit your needs. If you are interested to learn even more things to do, refer to the official documentation on traceback here

Now that we have seen how to exercise control over what gets printed and how to format them, next let us have a look at some best practices on when to use which piece of information

Best Practices while Printing Exception messages

When to Use Which Piece

  • Use Piece#1 only on very short programs and only during the development/testing phase to get some clues on the Exceptions without letting the interpreter crash your program. Once finding out, implement specific handlers to do something about these exceptions. If you are not sure how to handle the exceptions have a look at my other article below where I have explained 3 ways to handle Exceptions
    Exceptions in Python: Everything You Need To Know!
  • Use Piece#2 to print out some friendly information either for yourself or for your user to inform them what exactly is happening.
  • Use all 3 pieces on your finished product, so that if an exception ever occurs while your program is running on your client’s computer, you can log the errors and have use that information to fix your bugs.

Where to print

One point worth noting here is that the default file that print() uses is the stdout file stream and not the stderr stream. To use stderr instead, you can modify the code like this

import sys
try:
  #some naughty statements that irritate us with exceptions
except Exception as e:
  print(e, file=sys.stderr)

The above code is considered better practice, as errors are meant to go to stderr and not stdout.

You can always print these into a separate log file too if that is what you need. This way, you can organize the logs collected in a better manner by separating the informational printouts from the error printouts.

How to print into log files

If you are going to use a log file I suggest using python’s logging module instead of print() statements, as described here

If you are interested in learning how to manually raise exceptions, and what situations you might need to do that you can read this article below

Python: Manually throw/raise an Exception using the “raise” statement

If you are interested in catching and handling multiple exception in a single except clause, you can this article below

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

And with that, I will conclude this article!
I hope you enjoyed reading this article and got some value out of it!
Feel free to share it with your friends and colleagues!

How to catch and print the exception messages in Python

Sometimes, a Python script comes across an unusual situation that it can’t handle, and the program gets terminated or crashes. In this article, we’ll learn How to catch and print exception messages in Python which can help us better understand and debug such errors.

Step-by-Step Guide

When working with Python code, it’s crucial to handle errors effectively. You can achieve this by using ‘try-except’ statements or Python’s logging module, particularly ‘logger.exception()’. Here’s a step-by-step guide on how to catch and print exception messages in Python:

Using ‘try-except’:
1) Enclose the code you want to monitor for exceptions within a ‘try’ block.
2) Catch the exception using ‘except Exception as e’, where ‘e’ captures the exception object.
3) To print the exception message, simply use ‘print(e)’ or process it further.
Using ‘logger.exception()’:
1) Utilize Python’s logging module for a more structured approach.
2) Set up a logger instance using ‘import logging’ and ‘logger = logging.getLogger()’.
3) In your code, use ‘try’ and ‘except’ blocks to catch exceptions.
4) To log the exception message, use ‘logger.exception(“An exception occurred:”)’.

By following these methods, you can anticipate and manage errors in your Python code effectively, providing valuable insights into what went wrong during program execution.

Common Examples of Exception Messages

The most common example of an exception is a “FileNotFoundError” which is raised when you’re importing a file, but it doesn’t exist. Similarly, dividing a number by zero gives a “ZeroDivisionError” and displays a system-generated error message. All these run-time errors are known as exceptions. These exceptions should be caught and reported to prevent the program from being terminated.

In Python, exceptions are handled with the (try… except) statement. The statements which handle the exceptions are placed in the except block whereas the try clause includes the expressions which can raise an exception. Consider an example in which you take a list of integers as input from the user.

# Creating an empty list
new_list =[]

n = int(input("Enter number of elements : "))

for i in range(n):

    item = int(input())

    # Add the item in the list
    new_list.append(item)

print(new_list)

The program shown above takes integers as input and creates a list of these integers. If the user enters any character, the program will crash and generate the following output.

Output:


Enter number of elements : 7
23
45
34
65
2a
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-1-ac783af2c9a3> in <module>()
      3 n = int(input("Enter number of elements : "))
      4 for i in range(n):
----> 5     item = int(input())
      6     # Add the item in the list
      7     new_list.append(item)

ValueError: invalid literal for int() with base 10: '2a'

Different Methods to catch Exception messages

1) Using the Try and Except block

The first method to catch and print the exception messages in Python is by using except and try statements. If the user enters anything except the integer, we want the program to skip that input and move to the next value. In this way, our program will not crash and will catch and print the exception message. This can be done using try and except statements. Inside the try clause, we’ll take input from the user and append it to “new_list” variable. If the user has entered any input except integers mistakenly, the except block will print “Invalid entry” and move towards the next value. In this way, the program continues to run and skip the invalid entries.

# Creating an empty list
new_list =[]

n = int(input("Enter number of elements : "))

for i in range(n):

  try:
    item = int(input())

    # Add the item in the list
    new_list.append(item)

  except:

    print("Invalid Input!")

    print("Next entry.")

print("The list entered by user is: ", new_list)

Output:

Enter number of elements : 7
65
43
23
4df
Invalid Input!
Next entry.
76
54
90
The list entered by user is:  [65, 43, 23, 76, 54, 90]

There are various methods to catch and report these exceptions using try and except block. Some of them are listed below along with examples.

Catching and Reporting/Print exceptions messages in Python

This is the second method to catch and print the exception messages in Python. With the help of the print function, you can capture, get and print an exception message in Python. Consider an example in which you have a list containing elements of different data types. You want to divide all the integers by any number. This number on division with the string datatypes will raise “TypeError” and the program will terminate if the exceptions are not handled. The example shown below describes how to handle this problem by capturing the exception using the try-except block and reporting it using the print command.

list_arr=[76,65,87,"5f","7k",78,69]

for elem in list_arr:

  try:

    print("Result: ", elem/9)

  except Exception as e:

    print("Exception occurred for value '"+ elem + "': "+ repr(e))
Result:  8.444444444444445
Result:  7.222222222222222
Result:  9.666666666666666
Exception occurred for value '5f': TypeError("unsupported operand type(s) for /: 'str' and 'int'")
Exception occurred for value '7k': TypeError("unsupported operand type(s) for /: 'str' and 'int'")
Result:  8.666666666666666
Result:  7.666666666666667

print an Error message using try and logger.exception

Another method is to use logger.exception() which produces an error message as well as the log trace, which contains information such as the code line number at which the exception occurred and the time the exception occurred. This logger.exception() method should be included within the except statement; otherwise, it will not function properly.

import logging

logger=logging.getLogger()

num1=int(input("Enter the number 1:"))

num2=int(input("Enter the number 2:"))

try: 

  print("Result: ", num1/num2)

except Exception as e:

  logger.exception("Exception Occured while code Execution: "+ str(e))
Enter the number 1:82
Enter the number 2:4
Result:  20.5

Suppose a user enters 0 in the 2nd number, then this will raise a “ZeroDivisionError” as shown below.

Enter the number 1:9
Enter the number 2:0
Exception Occured while code Execution: division by zero
Traceback (most recent call last):
  File "<ipython-input-27-00694f615c2f>", line 11, in <module>
    print("Result: ", num1/num2)
ZeroDivisionError: division by zero

Similarly, if you’ve two lists consisting of integers and you want to create a list consisting of results obtained by dividing list1 with list2. Suppose you don’t know whether the two lists consist of integers or not.

import logging

logger=logging.getLogger()

list1=[45, 32, 76, 43, 0, 76]

list2=[24, "world", 5, 0, 4, 6]

Result=[]

for i in range(len(list1)):

  try:

    Result.append(list1[i]/list2[i])

  except Exception as e:

    logger.exception("Exception Occured while code Execution: "+ str(e))

print(Result)

In this example, “world” in the 2nd index of list2 is a string and 32 on division with a string would raise an exception. But, we have handled this exception using try and except block. The logger.exception() command prints the error along with the line at which it occurred and then moves toward the next index. Similarly, all the values are computed and stored in another list which is then displayed at the end of the code.


Exception Occured while code Execution: unsupported operand type(s) for /: 'int' and 'str'
Traceback (most recent call last):
  File "<ipython-input-1-5a40f7f6c621>", line 8, in <module>
    Result.append(list1[i]/list2[i])
TypeError: unsupported operand type(s) for /: 'int' and 'str'
Exception Occured while code Execution: division by zero
Traceback (most recent call last):
  File "<ipython-input-1-5a40f7f6c621>", line 8, in <module>
    Result.append(list1[i]/list2[i])
ZeroDivisionError: division by zero
[1.875, 15.2, 0.0, 12.666666666666666]

The logger module has another function “logger.error()” which returns only an error message. The following example demonstrates how the logger.error() function may be used to capture exception messages in Python. In this example, we have just replaced logger.exception in the above example with logger.error() function

import logging

logger=logging.getLogger()

list1=[45, 32,76,43,0, 76]

list2=[24, "world", 5, 0, 4, 6]

Result=[]

for i in range(len(list1)):

  try:

    Result.append(list1[i]/list2[i])

  except Exception as e:

    logger.error("Exception Occured while code Execution: "+ str(e))

print(Result)

Output:

Exception Occured while code Execution: unsupported operand type(s) for /: 'int' and 'str'
Exception Occured while code Execution: division by zero
[1.875, 15.2, 0.0, 12.666666666666666]

Catching and printing Specific Exception messages

The previous section was all about how to catch and print exceptions. But, how will you catch a specific exception such as Valueerror, ZeroDivisionError, ImportError, etc? There are two cases if you want to catch one specific exception or multiple specific exceptions. The following example shows how to catch a specific exception.

a = 'hello'

b = 4

try:

    print(a + b)

except TypeError as typo:

    print(typo)

Output:

can only concatenate str (not "int") to str

Similarly, if you want to print the result of “a/b” also and the user enters 0 as an input in variable “b”, then the same example would not be able to deal with ZeroDivisionError. Therefore we have to use multiple Except clauses as shown below.

a = 6

b = 0

try:

    print(a + b)

    print(a/b)

except TypeError as typo:

    print(typo)

except ZeroDivisionError as zer:

    print(zer)

The same code is now able to handle multiple exceptions.

6
division by zero

To summarize, all of the methods described above are effective and efficient. You may use any of the methods listed above to catch and print the exception messages in Python depending on your preferences and level of comfort with the method. If you’ve any queries regarding this article, please let us know in the comment section. Your feedback matters a lot to us.

Понравилась статья? Поделить с друзьями:

Интересное по теме:

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

  • Добавить комментарий

    ;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: