Python try except как получить текст ошибки

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'

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

Содержание

Введение
Пример с базовым Exception
Два исключения
except Error as e:: Печать текста ошибки
else
finally
raise
Пример 2
Пример 3
Исключения, которые не нужно обрабатывать
Список исключений
Разбор примеров: IndexError, ValueError, KeyError
Похожие статьи

Введение

Если в коде есть ошибка, которую видит интерпретатор поднимается исключение, создается так называемый
Exception Object, выполнение останавливается, в терминале
показывается Traceback.

В английском языке используется словосочетание Raise Exception

Исключение, которое не было предусмотрено разработчиком называется необработанным (Unhandled Exception)

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

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

Исключение, которое предусмотрено в коде называется обработанным (Handled)

Блок try except имеет следующий синтаксис

try:
pass
except Exception:
pass
else:
pass
finally:
pass

В этой статье я создал файл

try_except.py

куда копирую код из примеров.

Пример

Попробуем открыть несуществующий файл и воспользоваться базовым Exception

try:
f = open(‘missing.txt’)
except Exception:
print(‘ERR: File not found’)

python try_except.py

ERR: No missing.txt file found

Ошибка поймана, видно наше сообщение а не Traceback

Проверим, что когда файл существует всё хорошо

try:
f = open(‘existing.txt’)
except Exception:
print(‘ERR: File not found’)

python try_except.py

Пустота означает успех

Два исключения

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

try:
f = open(‘existing.txt’)
x = bad_value
except Exception:
print(‘ERR: File not found’)

python try_except.py

ERR: File not found

Файл открылся, но так как в следующей строке ошибка — в терминале появилось вводящее в заблуждение сообщение.
Проблема не в том, что «File not found» а в том, что bad_value нигде не определёно.

Избежать сбивающих с толку сообщений можно указав тип ожидаемой ошибки. В данном примере это FileNotFoundError

try:
# expected exception
f = open(‘existing.txt’)
# unexpected exception should result in Traceback
x = bad_value
except FileNotFoundError:
print(‘ERR: File not found’)

python try_except.py

Traceback (most recent call last):
File «/home/andrei/python/try_except2.py», line 5, in <module>
x = bad_value
NameError: name ‘bad_value’ is not defined

Вторая ошибка не поймана поэтому показан Traceback

Поймать обе ошибки можно добавив второй Exception

try:
# expected exception should be caught by FileNotFoundError
f = open(‘missing.txt’)
# unexpected exception should be caught by Exception
x = bad_value
except FileNotFoundError:
print(‘ERR: File not found’)
except Exception:
print(‘ERR: Something unexpected went wrong’)

python try_except.py

ERR: File not found

ERR: Something unexpected went wrong

Печать текста ошибки

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

try:
# expected exception should be caught by FileNotFoundError
f = open(‘existing.txt’)
# unexpected exception should be caught by Exception
x = bad_value
except FileNotFoundError as e:
print(e)
except Exception as e:
print(e)

python try_except.py

name ‘bad_value’ is not defined

Теперь попытаемся открыть несуществующий файл — должно быть две пойманные ошибки.

try:
# expected exception should be caught by FileNotFoundError
f = open(‘missing.txt’)
# unexpected exception should be caught by Exception
x = bad_value
except FileNotFoundError as e:
print(e)
except Exception as e:
print(e)

python try_except.py

name ‘bad_value’ is not defined

[Errno 2] No such file or directory: ‘missing.txt’

else

Блок else будет выполнен если исключений не будет поймано.

Попробуем открыть существующий файл

existing.txt

в котором есть строка

www.heihei.ru

try:
f = open(‘existing.txt’)
except FileNotFoundError as e:
print(e)
except Exception as e:
print(e)
else:
print(f.read())
f.close()

python try_except.py

www.heihei.ru

Если попробовать открыть несуществующий файл

missing.txt

то исключение обрабатывается, а код из блока else не выполняется.

[Errno 2] No such file or directory: ‘missing.txt’

finally

Блок finally будет выполнен независимо от того, поймано исключение или нет

try:
f = open(‘existing.txt’)
except FileNotFoundError as e:
print(e)
except Exception as e:
print(e)
else:
print(f.read())
f.close()
finally:
print(«Finally!»)

www.heihei.ru

Finally!

А если попытаться открыть несуществующий

missing.txt

[Errno 2] No such file or directory: ‘missing.txt’
Finally!

Когда нужно применять finally:

Рассмотрим скрипт, который вносит какие-то изменения в систему.
Затем он пытается что-то сделать. В конце возвращает
систему в исходное состояние.

Если ошибка случится в середине скрипта — он уже не сможет вернуть систему в исходное состояние.

Но если вынести возврат к исходному состоянию в блок finally он сработает даже при ошибке
в предыдущем блоке.

import os

def make_at(path, dir_name):
original_path = os.getcwd()
os.chdir(path)
os.mkdir(dir_name)
os.chdir(original_path)

Этот скрипт не вернётся в исходную директорию при ошибке в os.mkdir(dir_name)

А у скрипта ниже такой проблемы нет

def make_at(path, dir_name):
original_path = os.getcwd()
os.chdir(path)
try:
os.mkdir(dir_name)
finally:
os.chdir(original_path)

Не лишнима будет добавить обработку и вывод исключения

import os
import sys

def make_at(path, dir_name):
original_path = os.getcwd()
os.chdir(path)
try:
os.mkdir(dir_name)

except OSError as e:
print(e, file=sys.stderr)
raise
finally:
os.chdir(original_path)

По умолчанию print() выводит в sys.stdout, но в случае ислючений логичнее выводить в sys.stderr

raise

Можно вызывать исключения вручную в любом месте кода с помощью
raise.

try:
f = open(‘outdated.txt’)
if f.name == ‘outdated.txt’:
raise Exception
except FileNotFoundError as e:
print(e)
except Exception as e:
print(‘File is outdated!’)
else:
print(f.read())
f.close()
finally:
print(«Finally!»)

python try_except.py

File is outdated!
Finally!

raise

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

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

Пример 2

Рассмотрим функцию, которая принимает числа прописью и возвращает цифрами

DIGIT_MAP = {
‘zero’: ‘0’,
‘one’: ‘1’,
‘two’: ‘2’,
‘three’: ‘3’,
‘four’: ‘4’,
‘five’: ‘5’,
‘six’: ‘6’,
‘seven’: ‘7’,
‘eight’: ‘8’,
‘nine’: ‘9’,
}

def convert(s):
number = »
for token in s:
number += DIGIT_MAP[token]
x = int(number)
return x

python

>>> from exc1 import convert
>>> convert(«one three three seven».split())
1337

Теперь передадим аргумент, который не предусмотрен в словаре

>>> convert(«something unseen«.split())
Traceback (most recent call last):
File «<stdin>», line 1, in <module>
File «/home/andrei/python/exc1.py», line 17, in convert
number &plu= DIGIT_MAP[token]
KeyError: ‘something’

KeyError — это тип Exception объекта. Полный список можно изучить в конце статьи.

Исключение прошло следующий путь:

REPL convert() DIGIT_MAP(«something») KeyError

Обработать это исключение можно внеся изменения в функцию convert

convert(s):
try:
number = »
for token in s:
number += DIGIT_MAP[token]
x = int(number)
print(«Conversion succeeded! x = «, x)
except KeyError:
print(«Conversion failed!»)
x = —1
return x

>>> from exc1 import convert
>>> convert(«one nine six one».split())
Conversion succeeded! x = 1961
1961
>>> convert(«something unseen».split())
Conversion failed!
-1

Эта обработка не спасает если передать int вместо итерируемого объекта

>>> convert(2022)
Traceback (most recent call last):
File «<stdin>», line 1, in <module>
File «/home/andrei/python/exc1.py», line 17, in convert
for token in s:
TypeError: ‘int’ object is not iterable

Нужно добавить обработку TypeError


except KeyError:
print(«Conversion failed!»)
x = —1
except TypeError:
print(«Conversion failed!»)
x = —1
return x

>>> from exc1 import convert
>>> convert(«2022».split())
Conversion failed!
-1

Избавимся от повторов, удалив принты, объединив два исключения в кортеж и вынесем присваивание значения x
из try блока.

Также добавим

докстринг

с описанием функции.

def convert(s):
«»»Convert a string to an integer.»»»
x = —1
try:
number = »
for token in s:
number += DIGIT_MAP[token]
x = int(number)
except (KeyError, TypeError):
pass
return x

>>> from exc4 import convert
>>> convert(«one nine six one».split())
1961
>>> convert(«bad nine six one».split())
-1
>>> convert(2022)
-1

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

Грамотно показать текст сообщений об ошибках можно импортировав sys и изменив функцию

import sys

DIGIT_MAP = {
‘zero’: ‘0’,
‘one’: ‘1’,
‘two’: ‘2’,
‘three’: ‘3’,
‘four’: ‘4’,
‘five’: ‘5’,
‘six’: ‘6’,
‘seven’: ‘7’,
‘eight’: ‘8’,
‘nine’: ‘9’,
}

def convert(s):
«»»Convert a string to an integer.»»»
try:
number = »
for token in s:
number += DIGIT_MAP[token]
return(int(number))
except (KeyError, TypeError) as e:
print(f«Conversion error: {e!r}», file=sys.stderr)
return1

>>> from exc1 import convert
>>> convert(2022)
Conversion error: TypeError(«‘int’ object is not iterable»)
-1
>>> convert(«one nine six one».split())
1961
>>> convert(«bad nine six one».split())
Conversion error: KeyError(‘bad’)

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

С помощью

!r

выводится

repr()

ошибки

raise вместо кода ошибки

В предыдущем примере мы полагались на возвращение числа -1 в качестве кода ошибки.

Добавим к коду примера функцию string_log() и поработаем с ней

def string_log(s):
v = convert(s)
return log(v)

>>> from exc1 import string_log
>>> string_log(«one two eight».split())
4.852030263919617
>>> string_log(«bad one two».split())
Conversion error: KeyError(‘bad’)
Traceback (most recent call last):
File «<stdin>», line 1, in <module>
File «/home/andrei/exc1.py», line 32, in string_log
return log(v)
ValueError: math domain error

convert() вернул -1 а string_log попробовал его обработать и не смог.

Можно заменить return -1 на raise. Это считается более правильным подходом в Python

def convert(s):
«»»Convert a string to an integer.»»»
try:
number = »
for token in s:
number += DIGIT_MAP[token]
return(int(number))
except (KeyError, TypeError) as e:
print(f«Conversion error: {e!r}», file=sys.stderr)
raise

>>> from exc7 import string_log
>>> string_log(«one zero».split())
2.302585092994046
>>> string_log(«bad one two».split())
Conversion error: KeyError(‘bad’)
Traceback (most recent call last):
File «<stdin>», line 1, in <module>
File «/home/andrei/exc7.py», line 31, in string_log
v = convert(s)
File «/home/andrei/exc7.py», line 23, in convert
number += DIGIT_MAP[token]
KeyError: ‘bad’

Пример 3

Рассмотрим алгоритм по поиску квадратного корня

def sqrt(x):
«»»Compute square roots using the method
of Heron of Alexandria.

Args:
x: The number for which the square root
is to be computed.

Returns:
The square root of x.
«»»

guess = x
i = 0
while guess * guess != x and i < 20:
guess = (guess + x / guess) / 2.0
i += 1
return guess

def main():
print(sqrt(9))
print(sqrt(2))

if __name__ == ‘__main__’:
main()

python sqrt_ex.py

3.0
1.414213562373095

При попытке вычислить корень от -1 получим ошибку

def main():
print(sqrt(9))
print(sqrt(2))
print(sqrt(-1))

python sqrt_ex.py

3.0
1.414213562373095
Traceback (most recent call last):
File «/home/andrei/sqrt_ex.py», line 26, in <module>
main()
File «/home/andrei/sqrt_ex.py», line 23, in main
print(sqrt(-1))
File «/home/andrei/sqrt_ex.py», line 16, in sqrt
guess = (guess + x / guess) / 2.0
ZeroDivisionError: float division by zero

В строке

guess = (guess + x / guess) / 2.0

Происходит деление на ноль

Обработать можно следующим образом:

def main():
try:
print(sqrt(9))
print(sqrt(2))
print(sqrt(-1))
except ZeroDivisionError:
print(«Cannot compute square root «
«of a negative number.»)

print(«Program execution continues «
«normally here.»)

Обратите внимание на то, что в try помещены все вызовы функции

python sqrt_ex.py

3.0
1.414213562373095
Cannot compute square root of a negative number.
Program execution continues normally here.

Если пытаться делить на ноль несколько раз — поднимется одно исключение и всё что находится в блоке
try после выполняться не будет

def main():
try:
print(sqrt(9))
print(sqrt(-1))
print(sqrt(2))
print(sqrt(-1))

python sqrt_ex.py

3.0
Cannot compute square root of a negative number.
Program execution continues normally here.

Каждую попытку вычислить корень из -1 придётся обрабатывать отдельно. Это кажется неудобным, но
в этом и заключается смысл — каждое место где вы ждёте ислючение нужно помещать в свой
try except блок.

Можно обработать исключение так:

try:
while guess * guess != x and i < 20:
guess = (guess + x / guess) / 2.0
i += 1
except ZeroDivisionError:
raise ValueError()
return guess

def main():
print(sqrt(9))
print(sqrt(-1))

python sqrt_ex.py

3.0
Traceback (most recent call last):
File «/home/andrei/sqrt_ex3.py», line 17, in sqrt
guess = (guess + x / guess) / 2.0
ZeroDivisionError: float division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File «/home/andrei/sqrt_ex3.py», line 30, in <module>
main()
File «/home/andrei/sqrt_ex3.py», line 25, in main
print(sqrt(-1))
File «/home/andrei/sqrt_ex3.py», line 20, in sqrt
raise ValueError()
ValueError

Гораздо логичнее поднимать исключение сразу при получении аргумента

def sqrt(x):
«»»Compute square roots using the method
of Heron of Alexandria.

Args:
x: The number for which the square root
is to be computed.

Returns:
The square root of x.

Raises:
ValueError: If x is negative
«»»

if x < 0:
raise ValueError(
«Cannot compute square root of «
f«negative number {x}»)

guess = x
i = 0
while guess * guess != x and i < 20:
guess = (guess + x / guess) / 2.0
i += 1
return guess

def main():
print(sqrt(9))
print(sqrt(-1))
print(sqrt(2))
print(sqrt(-1))

if __name__ == ‘__main__’:
main()

python sqrt_ex.py

3.0
Traceback (most recent call last):
File «/home/avorotyn/python/lessons/pluralsight/core_python_getting_started/chapter8/sqrt_ex4.py», line 35, in <module>
main()
File «/home/avorotyn/python/lessons/pluralsight/core_python_getting_started/chapter8/sqrt_ex4.py», line 30, in main
print(sqrt(-1))
File «/home/avorotyn/python/lessons/pluralsight/core_python_getting_started/chapter8/sqrt_ex4.py», line 17, in sqrt
raise ValueError(
ValueError: Cannot compute square root of negative number -1

Пока получилось не очень — виден Traceback

Убрать Traceback можно добавив обработку ValueError в вызов функций

import sys

def sqrt(x):
«»»Compute square roots using the method
of Heron of Alexandria.

Args:
x: The number for which the square root
is to be computed.

Returns:
The square root of x.

Raises:
ValueError: If x is negative
«»»

if x < 0:
raise ValueError(
«Cannot compute square root of «
f«negative number {x}»)

guess = x
i = 0
while guess * guess != x and i < 20:
guess = (guess + x / guess) / 2.0
i += 1
return guess

def main():
try:
print(sqrt(9))
print(sqrt(2))
print(sqrt(-1))
print(«This is never printed»)
except ValueError as e:
print(e, file=sys.stderr)

print(«Program execution continues normally here.»)

if __name__ == ‘__main__’:
main()

python sqrt_ex.py

3.0
1.414213562373095
Cannot compute square root of negative number -1
Program execution continues normally here.

Исключения, которые не нужно обрабатывать

IndentationError, SyntaxError, NameError нужно исправлять в коде а не пытаться обработать.

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

Список исключений

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

Существуют следующие типы объектов Exception

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
+— EncodingWarning
+— ResourceWarning

IndexError

Объекты, которые поддерживают

протокол

Sequence должны поднимать исключение IndexError при использовании несуществующего индекса.

IndexError как и

KeyError

относится к ошибкам поиска LookupError

Пример

>>> a = [0, 1, 2]
>>> a[3]

Traceback (most recent call last):
File «<stdin>», line 1, in <module>
IndexError: list index out of range

ValueError

ValueError поднимается когда объект правильного типа, но содержит неправильное значение

>>> int(«text»)

Traceback (most recent call last):
File «<stdin>», line 1, in <module>
ValueError: invalid literal for int() with base 10: ‘text’

KeyError

KeyError поднимается когда поиск по ключам не даёт результата

>>> sites = dict(urn=1, heihei=2, eth1=3)
>>> sites[«topbicycle»]

Traceback (most recent call last):
File «<stdin>», line 1, in <module>
KeyError: ‘topbicycle’

TypeError

TypeError поднимается когда для успешного выполнения операции нужен объект
определённого типа, а предоставлен другой тип.

pi = 3.1415

text = «Pi is approximately « + pi

python str_ex.py

Traceback (most recent call last):
File «str_ex.py», line 3, in <module>
text = «Pi is approximately » + pi
TypeError: can only concatenate str (not «float») to str

Пример из статьи

str()

SyntaxError

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

Python 3.8.10 (default, Nov 14 2022, 12:59:47)
[GCC 9.4.0] on linux
Type «help», «copyright», «credits» or «license» for more information.
>>>
>>>
>>> 0 <> 0
File «<stdin>», line 1
0 <> 0
^
SyntaxError: invalid syntax

Пример из статьи

__future__

Похожие статьи

Python
Интерактивный режим
str: строки
\: перенос строки
Списки []
if, elif, else
Циклы
Функции
Пакеты
*args **kwargs
ООП
enum
Опеределить тип переменной Python
Тестирование с помощью Python
Работа с REST API на Python
Файлы: записать, прочитать, дописать, контекстный менеджер…
Скачать файл по сети
SQLite3: работа с БД
datetime: Дата и время в Python
json.dumps
Selenium + Python
Сложности при работе с Python
DJANGO
Flask
Скрипт для ZPL принтера
socket :Python Sockets
Виртуальное окружение
subprocess: выполнение bash команд из Python
multiprocessing: несколько процессов одновременно
psutil: cистемные ресурсы
sys.argv: аргументы командной строки
PyCharm: IDE
pydantic: валидация данных
paramiko: SSH из Python
enumerate
logging: запись в лог
Обучение программированию на 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!

Понравилась статья? Поделить с друзьями:
  • Qbittorrent выдает ошибку при скачивании
  • Python try except как вывести текст ошибки
  • Python средняя абсолютная ошибка
  • Python try except как вывести ошибку
  • Qbittorrent выдает ошибку ввода вывода