Python base error class

An overview of the Python exception class hierarchy, including a quick look at all the top-level exception classes in the standard library.

Nov 1, 2017 10:10:27 PM |
The Python Exception Class Hierarchy

An overview of the Python exception class hierarchy, including a quick look at all the top-level exception classes in the standard library.

The Python exception class hierarchy consists of a few dozen different exceptions spread across a handful of important base class types. As with most programming languages, errors occur within a Python application when something unexpected goes wrong. Anything from improper arithmetic and running out of memory to invalid file references and unicode formatting errors may be raised by Python under certain circumstances.

Most of the errors we’ll explore in this series are considered exceptions, which indicate that these are non-fatal errors. While a fatal error will halt execution of the current application, all non-fatal exceptions allow execution to continue. This allows our code to explicitly catch or rescue the raised exception and programmatically react to it in an appropriate manner.

Let’s start by looking at the full Python exception class hierarchy, as seen below:

  • BaseException
    • Exception
      • 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
      • StopIteration
      • StopAsyncIteration
      • SyntaxError
        • IndentationError
          • TabError
      • SystemError
      • TypeError
      • ValueError
        • UnicodeError
          • UnicodeDecodeError
          • UnicodeEncodeError
          • UnicodeTranslateError
      • Warning
        • BytesWarning
        • DeprecationWarning
        • FutureWarning
        • ImportWarning
        • PendingDeprecationWarning
        • ResourceWarning
        • RuntimeWarning
        • SyntaxWarning
        • UnicodeWarning
        • UserWarning
    • GeneratorExit
    • KeyboardInterrupt
    • SystemExit

As we publish future exception-specific articles in this series we’ll update the full list above to relevant tutorial and article links for each exception, so this post can act as a go-to resource for Python exception handling tips.

Major Exception Types Overview

Next, let’s briefly discuss each important top-level exception type. These top-level exceptions will serve as a basis for digging into specific exceptions in future articles. Before we do that, however, it’s worth pointing out what might appear as a slight discrepancy when looking over the list of exception classes provided in Python. To illustrate, look closely at this small snippet of the Python exception class hierarchy and see if anything slightly strange pops out to you:

  • BaseException
    • Exception
      • ArithmeticError
        • FloatingPointError
        • OverflowError
        • ZeroDivisionError
      • AssertionError

For developers that have worked with other programming languages in the past, what you might take note of is the distinction between using the word exception in the BaseException and Exception parent classes, and the use of error in most subclasses therein. Most other languages, such as .NET or Java, explicitly differentiate between exceptions and errors by separating them into distinct categories. In such languages, errors typically denote fatal errors (those that crash the application), whereas exceptions are catchable/rescuable errors.

Yet, as we see in the hierarchy above, Python merely inherits from Exception with a series of XYZError classes. The reason for this naming convention comes from the PEP8 Python style guide, which makes an explicit mention that «you should use the suffix ‘Error’ on your exception names (if the exception is actually an error).» I’ve added the extra emphasis to that quote, because the latter point is critical here — most Python exceptions with Error in the name are, in fact, errors.

BaseException

The BaseException class is, as the name suggests, the base class for all built-in exceptions in Python. Typically, this exception is never raised on its own, and should instead be inherited by other, lesser exception classes that can be raised.

The BaseException class (and, thus, all subclass exceptions as well) allows a tuple of arguments to be passed when creating a new instance of the class. In most cases, a single argument will be passed to an exception, which is a string value indicating the specific error message.

This class also includes a with_traceback(tb) method, which explicitly sets the new traceback information to the tb argument that was passed to it.

Exception

Exception is the most commonly-inherited exception type (outside of the true base class of BaseException). In addition, all exception classes that are considered errors are subclasses of the Exception class. In general, any custom exception class you create in your own code should inherit from Exception.

The Exception class contains many direct child subclasses that handle most Python errors, so we’ll briefly go over each below:

  • ArithmeticError — The base class for the variety of arithmetic errors, such as when attempting to divide by zero, or when an arithmetic result would be too large for Python to accurately represent.
  • AssertionError — This error is raised when a call to the [assert] statement fails.
  • AttributeError — Python’s syntax includes something called attribute references, which is just the Python way of describing what you might know of as dot notation. In essence, any primary token in Python (like an identifier, literal, and so forth) can be written and followed by a period (.), which is then followed by an identifier. That syntax (i.e. primary.identifier) is called an attribute reference, and anytime the executing script encounters an error in such syntax an AttributeError is raised.
  • BufferError — Python allows applications to access low level memory streams in the form of a buffer. For example, the bytes class can be used to directly work with bytes of information via a memory buffer. When something goes wrong within such a buffer operation a BufferError is raised.
  • EOFError — Similar to the Java EOFException article we did a few days ago, Python’s EOFError is raised when using the input() function and reaching the end of a file without any data.
  • ImportError — Modules are usually loaded in memory for Python scripts to use via the import statement (e.g. import car from vehicles). However, if an import attempt fails an ImportError will often be raised.
  • LookupError — Like ArithmeticError, the LookupError is generally considered a base class from which other subclasses should inherit. All LookupError subclasses deal with improper calls to a collection are made by using invalid key or index values.
  • MemoryError — In the event that your Python application is about to run out of memory a MemoryError will be raised. Since Python is smart enough to detect this potential issue slightly before all memory is used up, a MemoryError can be rescued and allow you to recover from the situation by performing garbage collection of some kind.
  • NameError — Raised when trying to use an identifier with an invalid or unknown name.
  • OSError — This error is raised when a system-level problem occurs, such as failing to find a local file on disk or running out of disk space entirely. OSError is a parent class to many subclasses explicitly used for certain issues related to operating system failure, so we’ll explore those in future publications.
  • ReferenceError — Python includes the weakref module, which allows Python code to create a specific type of reference known as a weak reference. A weak reference is a reference that is not «strong» enough to keep the referenced object alive. This means that the next cycle of garbage collection will identify the weakly referenced object as no longer strongly referenced by another object, causing the weakly referenced object to be destroyed to free up resources. If a weak reference proxy created via the weakref.proxy() function is used after the object that is referenced has already been destroyed via garbage collection, a ReferenceError will be raised.
  • RuntimeError — A RuntimeError is typically used as a catchall for when an error occurs that doesn’t really fit into any other specific error classification.
  • StopIteration — If no default value is passed to the next() function when iterating over a collection, and that collection has no more iterated value to retrieve, a StopIteration exception is raised. Note that this is not classified as an Error, since it doesn’t mean that an error has occurred.
  • StopAsyncIteration — As of version 3.5, Python now includes coroutines for asynchronous transactions using the async and await syntax. As part of this feature, collections can be asynchronously iterated using the __anext__() method. The __anext__() method requires that a StopAsyncIteration instance be raised in order to halt async iteration.
  • SyntaxError — Just like most programming languages, a SyntaxError in Python indicates that there is some improper syntax somewhere in your script file. A SyntaxError can be raised directly from an executing script, or produced via functions like eval() and exec().
  • SystemError — A generic error that is raised when something goes wrong with the Python interpreter (not to be confused with the OSError, which handles operating system issues).
  • TypeError — This error is raised when attempting to perform an operation on an incorrect object type.
  • ValueError — Should be raised when a function or method receives an argument of the correct type, but with an actual value that is invalid for some reason.
  • Warning — Another parent class to many subclasses, the Warning class is used to alert the user in non-dire situations. There are a number of subclass warnings that we’ll explore in future articles.

GeneratorExit

A generator is a specific type of iterator in Python, which simplifies the process of creating iterators with constantly changing values. By using the yield statement within a generator code block, Python will return or «generate» a new value for each call to next(). When the explicit generator.close() method is called a GeneratorExit instance is raised.

KeyboardInterrupt

This simple exception is raised when the user presses a key combination that causes an interrupt to the executing script. For example, many terminals accept Ctrl+C as an interrupt keystroke.

SystemExit

Finally, the SystemExit exception is raised when calling the sys.exit() method, which explicitly closes down the executing script and exits Python. Since this is an exception, it can be rescued and programmatically responded to immediately before the script actually shuts down.


That’s just a small taste of the powerful, built-in Python exception class hierarchy as of version 3.6. Stay tuned for more in-depth articles examining each of these exceptions in greater detail, and be sure to check out Airbrake’s robust error monitoring software, which provides real-time error monitoring and automatic exception reporting for all your development projects. Airbrake’s state of the art web dashboard ensures you receive round-the-clock status updates on your application’s health and error rates. No matter what you’re working on, Airbrake easily integrates with all the most popular languages and frameworks. Plus, Airbrake makes it easy to customize exception parameters, while giving you complete control of the active error filter system, so you only gather the errors that matter most.

Check out Airbrake’s error monitoring software today with a 14-day trial and see for yourself why so many of the world’s best engineering teams use Airbrake to revolutionize their exception handling practices!

Description¶

In the past, Python has supported simple string messages as exceptions as well as classes. Since 1.5, all of the standard library modules use classes for exceptions. Starting with Python 2.5, string exceptions result in a DeprecationWarning, and support for string exceptions will be removed in the future.

Base Classes¶

The exception classes are defined in a hierarchy, described in the standard library documentation. In addition to the obvious organizational benefits, exception inheritance is useful because related exceptions can be caught by catching their base class. In most cases, these base classes are not intended to be raised directly.

BaseException¶

Base class for all exceptions. Implements logic for creating a string
representation of the exception using str() from the arguments passed
to the constructor.

Exception¶

Base class for exceptions that do not result in quitting the running application.
All user-defined exceptions should use Exception as a base class.

StandardError¶

Base class for built-in exceptions used in the standard library.

ArithmeticError¶

Base class for math-related errors.

LookupError¶

Base class for errors raised when something can’t be found.

EnvironmentError¶

Base class for errors that come from outside of Python (the operating
system, filesystem, etc.).

Raised Exceptions¶

AssertionError¶

An AssertionError is raised by a failed assert statement.

assert False, 'The assertion failed'
$ python exceptions_AssertionError_assert.py

Traceback (most recent call last):
  File "exceptions_AssertionError_assert.py", line 12, in <module>
    assert False, 'The assertion failed'
AssertionError: The assertion failed

It is also used in the unittest module in methods like failIf().

import unittest

class AssertionExample(unittest.TestCase):
    
    def test(self):
        self.failUnless(False)

unittest.main()
$ python exceptions_AssertionError_unittest.py

F
======================================================================
FAIL: test (__main__.AssertionExample)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "exceptions_AssertionError_unittest.py", line 17, in test
    self.failUnless(False)
AssertionError: False is not true

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (failures=1)

AttributeError¶

When an attribute reference or assignment fails, AttributeError is
raised. For example, when trying to reference an attribute that does
not exist:

class NoAttributes(object):
    pass

o = NoAttributes()
print o.attribute
$ python exceptions_AttributeError.py

Traceback (most recent call last):
  File "exceptions_AttributeError.py", line 16, in <module>
    print o.attribute
AttributeError: 'NoAttributes' object has no attribute 'attribute'

Or when trying to modify a read-only attribute:

class MyClass(object):
    
    @property
    def attribute(self):
        return 'This is the attribute value'

o = MyClass()
print o.attribute
o.attribute = 'New value'
$ python exceptions_AttributeError_assignment.py

This is the attribute value
Traceback (most recent call last):
  File "exceptions_AttributeError_assignment.py", line 20, in <module>
    o.attribute = 'New value'
AttributeError: can't set attribute

EOFError¶

An EOFError is raised when a built-in function like input() or
raw_input() do not read any data before encountering the end of
their input stream. The file methods like read() return an empty
string at the end of the file.

while True:
    data = raw_input('prompt:')
    print 'READ:', data
$ echo hello | python PyMOTW/exceptions/exceptions_EOFError.py
prompt:READ: hello
prompt:Traceback (most recent call last):
  File "PyMOTW/exceptions/exceptions_EOFError.py", line 13, in <module>
    data = raw_input('prompt:')
EOFError: EOF when reading a line

FloatingPointError¶

Raised by floating point operations that result in errors, when
floating point exception control (fpectl) is turned on. Enabling
fpectl requires an interpreter compiled with the
—with-fpectl flag. Using fpectl is discouraged in the
stdlib docs.

import math
import fpectl

print 'Control off:', math.exp(1000)
fpectl.turnon_sigfpe()
print 'Control on:', math.exp(1000)

GeneratorExit¶

Raised inside a generator the generator’s close() method is called.

def my_generator():
    try:
        for i in range(5):
            print 'Yielding', i
            yield i
    except GeneratorExit:
        print 'Exiting early'

g = my_generator()
print g.next()
g.close()
$ python exceptions_GeneratorExit.py

Yielding 0
0
Exiting early

IOError¶

Raised when input or output fails, for example if a disk fills up or
an input file does not exist.

f = open('/does/not/exist', 'r')
$ python exceptions_IOError.py

Traceback (most recent call last):
  File "exceptions_IOError.py", line 12, in <module>
    f = open('/does/not/exist', 'r')
IOError: [Errno 2] No such file or directory: '/does/not/exist'

ImportError¶

Raised when a module, or member of a module, cannot be imported.
There are a few conditions where an ImportError might be raised.

  1. If a module does not exist.
import module_does_not_exist
$ python exceptions_ImportError_nomodule.py

Traceback (most recent call last):
  File "exceptions_ImportError_nomodule.py", line 12, in <module>
    import module_does_not_exist
ImportError: No module named module_does_not_exist

2. If from X import Y is used and Y cannot be found inside the
module X, an ImportError is raised.

from exceptions import MadeUpName
$ python exceptions_ImportError_missingname.py

Traceback (most recent call last):
  File "exceptions_ImportError_missingname.py", line 12, in <module>
    from exceptions import MadeUpName
ImportError: cannot import name MadeUpName

IndexError¶

An IndexError is raised when a sequence reference is out of range.

my_seq = [ 0, 1, 2 ]
print my_seq[3]
$ python exceptions_IndexError.py

Traceback (most recent call last):
  File "exceptions_IndexError.py", line 13, in <module>
    print my_seq[3]
IndexError: list index out of range

KeyError¶

Similarly, a KeyError is raised when a value is not found as a key of a dictionary.

d = { 'a':1, 'b':2 }
print d['c']
$ python exceptions_KeyError.py

Traceback (most recent call last):
  File "exceptions_KeyError.py", line 13, in <module>
    print d['c']
KeyError: 'c'

KeyboardInterrupt¶

A KeyboardInterrupt occurs whenever the user presses Ctrl-C (or
Delete) to stop a running program. Unlike most of the other
exceptions, KeyboardInterrupt inherits directly from BaseException to
avoid being caught by global exception handlers that catch Exception.

try:
    print 'Press Return or Ctrl-C:',
    ignored = raw_input()
except Exception, err:
    print 'Caught exception:', err
except KeyboardInterrupt, err:
    print 'Caught KeyboardInterrupt'
else:
    print 'No exception'

Pressing Ctrl-C at the prompt causes a KeyboardInterrupt exception.

$ python exceptions_KeyboardInterrupt.py
Press Return or Ctrl-C: ^CCaught KeyboardInterrupt

MemoryError¶

If your program runs out of memory and it is possible to recover (by
deleting some objects, for example), a MemoryError is raised.

import itertools

# Try to create a MemoryError by allocating a lot of memory
l = []
for i in range(3):
    try:
        for j in itertools.count(1):
            print i, j
            l.append('*' * (2**30))
    except MemoryError:
        print '(error, discarding existing list)'
        l = []
$ python exceptions_MemoryError.py
python(49670) malloc: *** mmap(size=1073745920) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
python(49670) malloc: *** mmap(size=1073745920) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
python(49670) malloc: *** mmap(size=1073745920) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
0 1
0 2
0 3
(error, discarding existing list)
1 1
1 2
1 3
(error, discarding existing list)
2 1
2 2
2 3
(error, discarding existing list)

NameError¶

NameErrors are raised when your code refers to a name that does not
exist in the current scope. For example, an unqualified variable
name.

def func():
    print unknown_name

func()
$ python exceptions_NameError.py

Traceback (most recent call last):
  File "exceptions_NameError.py", line 15, in <module>
    func()
  File "exceptions_NameError.py", line 13, in func
    print unknown_name
NameError: global name 'unknown_name' is not defined

NotImplementedError¶

User-defined base classes can raise NotImplementedError to indicate
that a method or behavior needs to be defined by a subclass,
simulating an interface.

class BaseClass(object):
    """Defines the interface"""
    def __init__(self):
        super(BaseClass, self).__init__()
    def do_something(self):
        """The interface, not implemented"""
        raise NotImplementedError(self.__class__.__name__ + '.do_something')

class SubClass(BaseClass):
    """Implementes the interface"""
    def do_something(self):
        """really does something"""
        print self.__class__.__name__ + ' doing something!'

SubClass().do_something()
BaseClass().do_something()
$ python exceptions_NotImplementedError.py

SubClass doing something!
Traceback (most recent call last):
  File "exceptions_NotImplementedError.py", line 27, in <module>
    BaseClass().do_something()
  File "exceptions_NotImplementedError.py", line 18, in do_something
    raise NotImplementedError(self.__class__.__name__ + '.do_something')
NotImplementedError: BaseClass.do_something

See also

abc — Abstract base classes

OSError¶

OSError serves as the error class for the os module, and is
raised when an error comes back from an os-specific function.

import os

for i in range(10):
    print i, os.ttyname(i)
$ python exceptions_OSError.py

0 /dev/ttys000
1
Traceback (most recent call last):
  File "exceptions_OSError.py", line 15, in <module>
    print i, os.ttyname(i)
OSError: [Errno 25] Inappropriate ioctl for device

OverflowError¶

When an arithmetic operation exceeds the limits of the variable type,
an OverflowError is raise. Long integers allocate more space as
values grow, so they end up raising MemoryError. Floating point
exception handling is not standardized, so floats are not checked.
Regular integers are converted to long values as needed.

import sys

print 'Regular integer: (maxint=%s)' % sys.maxint
try:
    i = sys.maxint * 3
    print 'No overflow for ', type(i), 'i =', i
except OverflowError, err:
    print 'Overflowed at ', i, err

print
print 'Long integer:'
for i in range(0, 100, 10):
    print '%2d' % i, 2L ** i

print
print 'Floating point values:'
try:
    f = 2.0**i
    for i in range(100):
        print i, f
        f = f ** 2
except OverflowError, err:
    print 'Overflowed after ', f, err
$ python exceptions_OverflowError.py

Regular integer: (maxint=9223372036854775807)
No overflow for  <type 'long'> i = 27670116110564327421

Long integer:
 0 1
10 1024
20 1048576
30 1073741824
40 1099511627776
50 1125899906842624
60 1152921504606846976
70 1180591620717411303424
80 1208925819614629174706176
90 1237940039285380274899124224

Floating point values:
0 1.23794003929e+27
1 1.53249554087e+54
2 2.34854258277e+108
3 5.5156522631e+216
Overflowed after  5.5156522631e+216 (34, 'Result too large')

ReferenceError¶

When a weakref proxy is used to access an object that has
already been garbage collected, a ReferenceError occurs.

import gc
import weakref

class ExpensiveObject(object):
    def __init__(self, name):
        self.name = name
    def __del__(self):
        print '(Deleting %s)' % self

obj = ExpensiveObject('obj')
p = weakref.proxy(obj)

print 'BEFORE:', p.name
obj = None
print 'AFTER:', p.name
$ python exceptions_ReferenceError.py

BEFORE: obj
(Deleting <__main__.ExpensiveObject object at 0x10046e4d0>)
AFTER:
Traceback (most recent call last):
  File "exceptions_ReferenceError.py", line 26, in <module>
    print 'AFTER:', p.name
ReferenceError: weakly-referenced object no longer exists

RuntimeError¶

A RuntimeError exception is used when no other more specific exception
applies. The interpreter does not raise this exception itself very
often, but some user code does.

StopIteration¶

When an iterator is done, it’s next() method raises StopIteration.
This exception is not considered an error.

l=[0,1,2]
i=iter(l)

print i
print i.next()
print i.next()
print i.next()
print i.next()
$ python exceptions_StopIteration.py

<listiterator object at 0x10045f650>
0
1
2
Traceback (most recent call last):
  File "exceptions_StopIteration.py", line 19, in <module>
    print i.next()
StopIteration

SyntaxError¶

A SyntaxError occurs any time the parser finds source code it does not
understand. This can be while importing a module, invoking exec,
or calling eval(). Attributes of the exception can be used to
find exactly what part of the input text caused the exception.

try:
    print eval('five times three')
except SyntaxError, err:
    print 'Syntax error %s (%s-%s): %s' % 
        (err.filename, err.lineno, err.offset, err.text)
    print err
$ python exceptions_SyntaxError.py

Syntax error <string> (1-10): five times three
invalid syntax (<string>, line 1)

SystemError¶

When an error occurs in the interpreter itself and there is some
chance of continuing to run successfully, it raises a SystemError.
SystemErrors probably indicate a bug in the interpreter and should be
reported to the maintainer.

SystemExit¶

When sys.exit() is called, it raises SystemExit instead of exiting
immediately. This allows cleanup code in try:finally blocks to
run and special environments (like debuggers and test frameworks) to
catch the exception and avoid exiting.

TypeError¶

TypeErrors are caused by combining the wrong type of objects, or
calling a function with the wrong type of object.

result = ('tuple',) + 'string'
$ python exceptions_TypeError.py

Traceback (most recent call last):
  File "exceptions_TypeError.py", line 12, in <module>
    result = ('tuple',) + 'string'
TypeError: can only concatenate tuple (not "str") to tuple

UnboundLocalError¶

An UnboundLocalError is a type of NameError specific to local variable
names.

def throws_global_name_error():
    print unknown_global_name

def throws_unbound_local():
    local_val = local_val + 1
    print local_val

try:
    throws_global_name_error()
except NameError, err:
    print 'Global name error:', err

try:
    throws_unbound_local()
except UnboundLocalError, err:
    print 'Local name error:', err

The difference between the global NameError and the UnboundLocal is
the way the name is used. Because the name “local_val” appears on the
left side of an expression, it is interpreted as a local variable
name.

$ python exceptions_UnboundLocalError.py

Global name error: global name 'unknown_global_name' is not defined
Local name error: local variable 'local_val' referenced before assignment

UnicodeError¶

UnicodeError is a subclass of ValueError and is
raised when a Unicode problem occurs. There are separate subclasses
for UnicodeEncodeError, UnicodeDecodeError, and
UnicodeTranslateError.

ValueError¶

A ValueError is used when a function receives a value that has the
right type but an invalid value.

$ python exceptions_ValueError.py

Traceback (most recent call last):
  File "exceptions_ValueError.py", line 12, in <module>
    print chr(1024)
ValueError: chr() arg not in range(256)

ZeroDivisionError¶

When zero shows up in the denominator of a division operation, a
ZeroDivisionError is raised.

$ python exceptions_ZeroDivisionError.py

Traceback (most recent call last):
  File "exceptions_ZeroDivisionError.py", line 12, in <module>
    print 1/0
ZeroDivisionError: integer division or modulo by zero

Warning Categories¶

There are also several exceptions defined for use with the warnings module.

Warning
The base class for all warnings.
UserWarning
Base class for warnings coming from user code.
DeprecationWarning
Used for features no longer being maintained.
PendingDeprecationWarning
Used for features that are soon going to be deprecated.
SyntaxWarning
Used for questionable syntax.
RuntimeWarning
Used for events that happen at runtime that might cause problems.
FutureWarning
Warning about changes to the language or library that are coming at a later time.
ImportWarning
Warn about problems importing a module.
UnicodeWarning
Warn about problems with unicode text.

See also

exceptions
The standard library documentation for this module.
warnings
Non-error warning messages.

Содержание:

  • Базовый класс для встроенных исключений BaseException,
  • Базовый класс пользовательских исключений Exception,
  • Базовый класс арифметических исключений ArithmeticError,
  • Базовый класс исключений связанных с буфером BufferError,
  • Базовый класс исключений связанных с индексированием LookupError,

BaseException:

Базовый класс для всех встроенных исключений. Он не предназначен для прямого наследования определяемыми пользователем классами, для этого используйте исключение Exception. Если функция str() вызывается на экземпляре этого класса, то возвращается представление аргумента(ов) к экземпляру или пустая строка, когда аргументов не было.

Атрибуты и методы BaseException:

BaseException.args:

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

BaseException.with_traceback(tb):

Метод BaseException.with_traceback(tb) устанавливает аргумент tb в качестве новой обратной трассировки для исключения и возвращает объект исключения. Он обычно используется в коде обработки исключений, как это:

try:
     ... 
 except SomeException:
     tb = sys.exc_info()[2]
     raise OtherException(...).with_traceback(tb)
BaseException.add_note(note):

Метод BaseException.add_note() добавляет строку примечания к примечаниям исключения, которые появляются в стандартной трассировке после строки исключения. Ошибка TypeError возникает, если аргумент note не является строкой.

Добавлен в Python 3.11.

BaseException.__notes__:

Атрибут BaseException.__notes__ — это список заметок этого исключения, которые были добавлены с помощью BaseException.add_note(). Этот атрибут создается при вызове метода BaseException.add_note().

Добавлен в Python 3.11.

Exception:

ArithmeticError:

Исключение ArithmeticError это базовый класс для трех встроенных исключений, которые поднимаются для различных арифметических ошибок:

  • OverflowError,
  • ZeroDivisionError,
  • FloatingPointError.

BufferError:

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

LookupError:

Исключение LookupError это базовый класс для исключений, которые возникают, когда ключ или индекс, используемые в отображении или последовательности, недопустимы: IndexError, KeyError. Исключение LookupError можно поднять напрямую codecs.lookup().

Improve Article

Save Article

  • Read
  • Discuss
  • Improve Article

    Save Article

    All instances in Python must be instances of a class that derives from BaseException. Two exception classes that are not related via subclassing are never equivalent, even if they have the same name. The built-in exceptions can be generated by the interpreter or built-in functions.

    There are several built-in exceptions in Python that are raised when errors occur. These built-in exceptions can be viewed using the local() built-in functions as follows :

    >>> locals()['__builtins__']
    

    This returns a dictionary of built-in exceptions, functions and attributes.

    Base Classes

    The following exceptions are used mostly as base classes for other exceptions.

    1. exception BaseException
      This is the base class for all built-in exceptions. It is not meant to be directly inherited by user-defined classes. For, user-defined classes, Exception is used. This class is responsible for creating a string representation of the exception using str() using the arguments passed. An empty string is returned if there are no arguments.
      • args : The args are the tuple of arguments given to the exception constructor.
      • with_traceback(tb) : This method is usually used in exception handling. This method sets tb as the new traceback for the exception and returns the exception object.

        Code :

        try:
            ...
        except SomeException:
            tb = sys.exc_info()[2]
            raise OtherException(...).with_traceback(tb)
        
    2. exception Exception
      This is the base class for all built-in non-system-exiting exceptions. All user-defined exceptions should also be derived from this class.
    3. exception ArithmeticError
      This class is the base class for those built-in exceptions that are raised for various arithmetic errors such as :
      • OverflowError
      • ZeroDivisionError
      • FloatingPointError

      Example :

      try:  

          a = 10/0  

          print (a)

      except ArithmeticError:  

              print ("This statement is raising an arithmetic exception.")

      else:  

          print ("Success.")

      Output :

      This statement is raising an arithmetic exception.
      
    4. exception BufferError
      This exception is raised when buffer related operations cannot be performed.
    5. exception LookupError
      This is the base class for those exceptions that are raised when a key or index used on a mapping or sequence is invalid or not found. The exceptions raised are :
      • KeyError
      • IndexError

      Example :

      try

          a = [1, 2, 3

          print (a[3]) 

      except LookupError: 

          print ("Index out of bound error.")

      else

          print ("Success")

      Output :

      Index out of bound error.
      

    Concrete exceptions

    The following exceptions are the exceptions that are usually raised.

    1. exception AssertionError
      An AssertionError is raised when an assert statement fails.

      Example :

      assert False, 'The assertion failed'
      

      Output :

      Traceback (most recent call last):
        File "exceptions_AssertionError.py", line 12, in 
          assert False, 'The assertion failed'
      AssertionError: The assertion failed
      
    2. exception AttributeError
      An AttributeError is raised when an attribute reference or assignment fails such as when a non-existent attribute is referenced.

      Example :

      class Attributes(object):

          pass

      object = Attributes()

      print (object.attribute)

      Output :

      Traceback (most recent call last):
        File "d912bae549a2b42953bc62da114ae7a7.py", line 5, in 
          print object.attribute
      AttributeError: 'Attributes' object has no attribute 'attribute'
      
    3. exception EOFError
      An EOFError is raised when built-in functions like input() hits an end-of-file condition (EOF) without reading any data. The file methods like readline() return an empty string when they hit EOF.

      Example :

      while True:

          data = input('Enter name : ')

          print ('Hello  ', data)

      Output :

      Enter Name :Hello Aditi
      Enter Name :Traceback (most recent call last):
        File "exceptions_EOFError.py", line 13, in 
          data = raw_input('Enter name :')
      EOFError: EOF when reading a line
      
    4. exception FloatingPointError
      A FloatingPointError is raised when a floating point operation fails. This exception is always defined, but can only be raised when Python is configured with the–with-fpectl option, or the WANT_SIGFPE_HANDLER symbol is defined in the pyconfig.h file.

      Example :

      import math

      print (math.exp(1000))

      Output :

      Traceback (most recent call last):
        File "", line 1, in 
      FloatingPointError: in math_1
      
    5. exception GeneratorExit
      This exception directly inherits from BaseException instead of Exception since it is technically not an error. A GeneratorExit exception is raised when a generator or coroutine is closed.

      Example :

      def my_generator():

          try:

              for i in range(5):

                  print ('Yielding', i)

                  yield i

          except GeneratorExit:

              print ('Exiting early')

      g = my_generator()

      print (g.next())

      g.close()

      Output :

      Yielding 0
      0
      Exiting early
      
    6. exception ImportError
      An ImportError is raised when the import statement is unable to load a module or when the “from list” in from … import has a name that cannot be found.

        Example :

        import module_does_not_exist

        Output :

        Traceback (most recent call last):
          File "exceptions_ImportError_nomodule.py", line 12, in 
            import module_does_not_exist
        ImportError: No module named module_does_not_exist
        
        

        Example :

        from exceptions import Userexception

        Output :

        Traceback (most recent call last):
          File "exceptions_ImportError_missingname.py", line 12, in 
            from exceptions import Userexception
        ImportError: cannot import name Userexception
        
        
    7. exception ModuleNotFoundError
      This is the subclass of ImportError which is raised by import when a module could not be found. It is also raised when None is found in sys.modules.
    8. exception IndexError
      An IndexError is raised when a sequence is referenced which is out of range.

      Example :

      array = [ 0, 1, 2 ]

      print (array[3])

      Output :

      Traceback (most recent call last):
        File "exceptions_IndexError.py", line 13, in 
          print array[3]
      IndexError: list index out of range
      
    9. exception KeyError
      A KeyError is raised when a mapping key is not found in the set of existing keys.

      Example :

      array = { 'a':1, 'b':2 }

      print (array['c'])

      Output :

      Traceback (most recent call last):
        File "exceptions_KeyError.py", line 13, in 
          print array['c']
      KeyError: 'c'
      
    10. exception KeyboardInterrupt
      This error is raised when the user hits the interrupt key such as Control-C or Delete.

      Example :

      try:

          print ('Press Return or Ctrl-C:',)

          ignored = input()

      except Exception, err:

          print ('Caught exception:', err)

      except KeyboardInterrupt, err:

          print ('Caught KeyboardInterrupt')

      else:

          print ('No exception')

      Output :

      Press Return or Ctrl-C: ^CCaught KeyboardInterrupt
      
    11. exception MemoryError
      This error is raised when an operation runs out of memory.

      Example :

      def fact(a):

          factors = []

          for i in range(1, a+1):

              if a%i == 0:

                  factors.append(i)

          return factors 

      num = 600851475143

      print (fact(num))

      Output :

      Traceback (most recent call last):
        File "4af5c316c749aff128df20714536b8f3.py", line 9, in 
          print fact(num)
        File "4af5c316c749aff128df20714536b8f3.py", line 3, in fact
          for i in range(1, a+1):
      MemoryError
      
    12. exception NameError
      This error is raised when a local or global name is not found. For example, an unqualified variable name.

      Example :

      def func():

          print ans

      func()

      Output :

      Traceback (most recent call last):
        File "cfba0a5196b05397e0a23b1b5b8c7e19.py", line 4, in 
          func()
        File "cfba0a5196b05397e0a23b1b5b8c7e19.py", line 2, in func
          print ans
      NameError: global name 'ans' is not defined
      
    13. exception NotImplementedError
      This exception is derived from RuntimeError. Abstract methods in user defined classed should raise this exception when the derived classes override the method.

      Example :

      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__ + ' doing something!')

      SubClass().do_something()

      BaseClass().do_something()

      Output :

      Traceback (most recent call last):
        File "b32fc445850cbc23cd2f081ba1c1d60b.py", line 16, in 
          BaseClass().do_something()
        File "b32fc445850cbc23cd2f081ba1c1d60b.py", line 7, in do_something
          raise NotImplementedError(self.__class__.__name__ + '.do_something')
      NotImplementedError: BaseClass.do_something
      
    14. exception OSError([arg])
      The OSError exception is raised when a system function returns a system-related error, including I/O failures such as “file not found” or “disk full” errors.

      Example :

      def func():

          print (ans)

      func()

      Output :

      Traceback (most recent call last):
        File "442eccd7535a2704adbe372cb731fc0f.py", line 4, in 
          print i, os.ttyname(i)
      OSError: [Errno 25] Inappropriate ioctl for device
      
    15. exception OverflowError
      The OverflowError is raised when the result of an arithmetic operation is out of range. Integers raise MemoryError instead of OverflowError. OverflowError is sometimes raised for integers that are outside a required range. Floating point operations are not checked because of the lack of standardization of floating point exception handling in C.

      Example :

      import sys

      print ('Regular integer: (maxint=%s)' % sys.maxint)

      try:

          i = sys.maxint * 3

          print ('No overflow for ', type(i), 'i =', i)

      except OverflowError, err:

          print ('Overflowed at ', i, err)

      print()

      print ('Long integer:')

      for i in range(0, 100, 10):

          print ('%2d' % i, 2L ** i)

      print()

      print ('Floating point values:')

      try:

          f = 2.0**i

          for i in range(100):

              print (i, f)

              f = f ** 2

      except OverflowError, err:

          print ('Overflowed after ', f, err)

      Output :

      Regular integer: (maxint=9223372036854775807)
      No overflow for   i = 27670116110564327421
      
      Long integer:
       0 1
      10 1024
      20 1048576
      30 1073741824
      40 1099511627776
      50 1125899906842624
      60 1152921504606846976
      70 1180591620717411303424
      80 1208925819614629174706176
      90 1237940039285380274899124224
      
      Floating point values:
      0 1.23794003929e+27
      1 1.53249554087e+54
      2 2.34854258277e+108
      3 5.5156522631e+216
      Overflowed after  5.5156522631e+216 (34, 'Numerical result out of range')
      
      
    16. exception RecursionError
      The RecursionError is derived from the RuntimeError. This exception is raised when the interpreter detects that the maximum recursion depth is exceeded.
    17. exception ReferenceError
      The ReferenceError is raised when a weak reference proxy is used to access an attribute of the referent after the garbage collection.

      Example :

      import gc

      import weakref

      class Foo(object):

          def __init__(self, name):

              self.name = name

          def __del__(self):

              print ('(Deleting %s)' % self)

      obj = Foo('obj')

      p = weakref.proxy(obj)

      print ('BEFORE:', p.name)

      obj = None

      print ('AFTER:', p.name)

      Output :

      BEFORE: obj
      (Deleting )
      AFTER:
      
      Traceback (most recent call last):
        File "49d0c29d8fe607b862c02f4e1cb6c756.py", line 17, in 
          print 'AFTER:', p.name
      ReferenceError: weakly-referenced object no longer exists
      
    18. exception RuntimeError
      The RuntimeError is raised when no other exception applies. It returns a string indicating what precisely went wrong.
    19. exception StopIteration
      The StopIteration error is raised by built-in function next() and an iterator‘s __next__() method to signal that all items are produced by the iterator.

      Example :

      Arr = [3, 1, 2]

      i=iter(Arr)

      print (i)

      print (i.next())

      print (i.next())

      print (i.next())

      print (i.next())

      Output :

      3
      1
      2
      
      Traceback (most recent call last):
        File "2136fa9a620e14f8436bb60d5395cc5b.py", line 8, in 
          print i.next()
      StopIteration
      
    20. exception SyntaxError
      The SyntaxError is raised when the parser encounters a syntax error. A syntax error may occur in an import statement or while calling the built-in functions exec() or eval(), or when reading the initial script or standard input.

      Example :

      try:

          print (eval('geeks for geeks'))

      except SyntaxError, err:

          print ('Syntax error %s (%s-%s): %s' %

              (err.filename, err.lineno, err.offset, err.text))

          print (err)

      Output :

      Syntax error  (1-9): geeks for geeks
      invalid syntax (, line 1)
      
    21. exception SystemError
      The SystemError is raised when the interpreter finds an internal error. The associated value is a string indicating what went wrong.
    22. exception SystemExit
      The SystemExit is raised when sys.exit() function is called. A call to sys.exit() is translated into an exception to execute clean-up handlers (finally clauses of try statements) and to debug a script without running the risk of losing control.
    23. exception TypeError
      TypeError is raised when an operation or function is applied to an object of inappropriate type. This exception returns a string giving details about the type mismatch.

      Example :

      arr = ('tuple', ) + 'string'

      print (arr)

      Output :

      Traceback (most recent call last):
        File "30238c120c0868eba7e13a06c0b1b1e4.py", line 1, in 
          arr = ('tuple', ) + 'string'
      TypeError: can only concatenate tuple (not "str") to tuple
      
    24. exception UnboundLocalError
      UnboundLocalError is a subclass of NameError which is raised when a reference is made to a local variable in a function or method, but no value has been assigned to that variable.

      Example :

      def global_name_error():

          print (unknown_global_name)

      def unbound_local():

          local_val = local_val + 1

          print (local_val)

      try:

          global_name_error()

      except NameError, err:

          print ('Global name error:', err)

      try:

          unbound_local()

      except UnboundLocalError, err:

          print ('Local name error:', err)

      Output :

      Global name error: global name 'unknown_global_name' is not defined
      Local name error: local variable 'local_val' referenced before assignment
      
    25. exception UnicodeError
      This exception is a subclass of ValueError. UnicodeError is raised when a Unicode-related encoding or decoding error occurs.
    26. exception ValueError
      A ValueError is raised when a built-in operation or function receives an argument that has the right type but an invalid value.

      Example :

      Output :

      Traceback (most recent call last):
        File "44f00efda935715a3c5468d899080381.py", line 1, in 
          print int('a')
      ValueError: invalid literal for int() with base 10: 'a'
      
    27. exception ZeroDivisionError
      A ZeroDivisionError is raised when the second argument of a division or modulo operation is zero. This exception returns a string indicating the type of the operands and the operation.

      Example :

      Output :

      Traceback (most recent call last):
        File "c31d9626b41e53d170a78eac7d98cb85.py", line 1, in 
          print 1/0
      ZeroDivisionError: integer division or modulo by zero
      

    This article is contributed by Aditi Gupta. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

    Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

    Three years after my definitive guide on Python classic, static, class and abstract methods, it seems to be time for a new one. Here, I would like to dissect and discuss Python exceptions.

    Dissecting the base exceptions

    In Python, the base exception class is named BaseException. Being rarely used in any program or library, it ought to be considered as an implementation detail. But to discover how it’s implemented, you can go and read Objects/exceptions.c in the CPython source code. In that file, what is interesting is to see that the BaseException class defines all the basic methods and attribute of exceptions. The basic well-known Exception class is then simply defined as a subclass of BaseException, nothing more:

    /*
     *    Exception extends BaseException
     */
    SimpleExtendsException(PyExc_BaseException, Exception,
                           "Common base class for all non-exit exceptions.");
    

    The only other exceptions that inherits directly from BaseException are GeneratorExit, SystemExit and KeyboardInterrupt. All the other builtin exceptions inherits from Exception. The whole hierarchy can be seen by running pydoc2 exceptions or pydoc3 builtins.

    Here are the graph representing the builtin exceptions inheritance in Python 2 and Python 3 (generated using this script).

    Python 2 builtin exceptions inheritance graph
    Python 3 builtin exceptions inheritance graph

    The BaseException.__init__ signature is actually BaseException.__init__(*args). This initialization method stores any arguments that is passed in the args attribute of the exception. This can be seen in the exceptions.c source code – and is true for both Python 2 and Python 3:

    static int
    BaseException_init(PyBaseExceptionObject *self, PyObject *args, PyObject *kwds)
    {
        if (!_PyArg_NoKeywords(Py_TYPE(self)->tp_name, kwds))
            return -1;
    
        Py_INCREF(args);
        Py_XSETREF(self->args, args);
    
        return 0;
    }
    

    The only place where this args attribute is used is in the BaseException.__str__ method. This method uses self.args to convert an exception to a string:

    static PyObject *
    BaseException_str(PyBaseExceptionObject *self)
    {
        switch (PyTuple_GET_SIZE(self->args)) {
        case 0:
            return PyUnicode_FromString("");
        case 1:
            return PyObject_Str(PyTuple_GET_ITEM(self->args, 0));
        default:
            return PyObject_Str(self->args);
        }
    }
    

    This can be translated in Python to:

    def __str__(self):
        if len(self.args) == 0:
            return ""
        if len(self.args) == 1:
            return str(self.args[0])
        return str(self.args)
    

    Therefore, the message to display for an exception should be passed as the first and the only argument to the BaseException.__init__ method.

    Defining your exceptions properly

    As you may already know, in Python, exceptions can be raised in any part of the program. The basic exception is called Exception and can be used anywhere in your program. In real life, however no program nor library should ever raise Exception directly: it’s not specific enough to be helpful.

    Since all exceptions are expected to be derived from the base class Exception, this base class can easily be used as a catch-all:

    try:
        do_something()
    except Exception:
        # THis will catch any exception!
        print("Something terrible happened")
    

    To define your own exceptions correctly, there are a few rules and best practice that you need to follow:

    • Always inherit from (at least) Exception:
    class MyOwnError(Exception):
        pass
    
    • Leverage what we saw earlier about BaseException.__str__: it uses the first argument passed to BaseException.__init__ to be printed, so always call BaseException.__init__ with only one argument.

    • When building a library, define a base class inheriting from Excepion. It will make it easier for consumers to catch any exception from the library:

    class ShoeError(Exception):
        """Basic exception for errors raised by shoes"""
    
    class UntiedShoelace(ShoeError):
        """You could fall"""
    
    class WrongFoot(ShoeError):
        """When you try to wear your left show on your right foot"""
    

    It then makes it easy to use except ShoeError when doing anything with that piece of code related to shoes. For example, Django does not do that for some of its exceptions, making it hard to catch «any exception raised by Django».

    • Provide details about the error. This is extremely valuable to be able to log correctly errors or take further action and try to recover:
    class CarError(Exception):
        """Basic exception for errors raised by cars"""
        def __init__(self, car, msg=None):
            if msg is None:
                # Set some default useful error message
                msg = "An error occured with car %s" % car
            super(CarError, self).__init__(msg)
            self.car = car
    
    class CarCrashError(CarError):
        """When you drive too fast"""
        def __init__(self, car, other_car, speed):
            super(CarCrashError, self).__init__(
                car, msg="Car crashed into %s at speed %d" % (other_car, speed))
            self.speed = speed
            self.other_car = other_car
    

    Then, any code can inspect the exception to take further action:

    try:
        drive_car(car)
    except CarCrashError as e:
        # If we crash at high speed, we call emergency
        if e.speed >= 30:
            call_911()
    

    For example, this is leveraged in Gnocchi to raise specific application exceptions (NoSuchArchivePolicy) on expected foreign key violations raised by SQL constraints:

    try:
        with self.facade.writer() as session:
            session.add(m)
    except exception.DBReferenceError as e:
        if e.constraint == 'fk_metric_ap_name_ap_name':
            raise indexer.NoSuchArchivePolicy(archive_policy_name)
        raise
    
    • Inherits from builtin exceptions types when it makes sense. This makes it easier for programs to not be specific to your application or library:
    class CarError(Exception):
        """Basic exception for errors raised by cars"""
    
    class InvalidColor(CarError, ValueError):
        """Raised when the color for a car is invalid"""
    

    That allows many programs to catch errors in a more generic way without noticing your own defined type. If a program already knows how to handle a ValueError, it won’t need any specific code nor modification.

    Organization

    Organizing code can be quite touchy and complicated. I cover more general rules in The Hacker’s Guide to Python, but here’s a few rules concerning exceptions in particular.

    There is no limitation on where and when you can define exceptions. As they are, after all, normal classes, they can be defined in any module, function or class – even as closures.

    Most libraries package their exceptions into a specific exception module: SQLAlchemy has them in
    sqlalchemy.exc, requests has them in
    requests.exceptions, Werkzeug has them in werkzeug.exceptions, etc.

    That makes sense for libraries to export exceptions that way, as it makes it very easy for consumers to import their exception module and know where the exceptions are defined when writing code to handle errors.

    This is not mandatory, and smaller Python modules might want to retain their exceptions into their sole module. Typically, if your module is small enough to be kept in one file, don’t bother splitting your exceptions into a different file/module.

    While this wisely applies to libraries, applications tend to be different beasts. Usually, they are composed of different subsystems, where each one might have its own set of exceptions. This is why I generally discourage going with only one exception module in an application, but to split them across the different parts of one’s program. There might be no need of a special myapp.exceptions module.

    For example, if your application is composed of an HTTP REST API defined into the module myapp.http and of a TCP server contained into myapp.tcp, it’s likely they can both define different exceptions tied to their own protocol errors and cycle of life. Defining those exceptions in a myapp.exceptions module would just scatter the code for the sake of some useless consistency. If the exceptions are local to a file, just define them somewhere at the top of that file. It will simplify the maintenance of the code.

    Wrapping exceptions

    Wrapping exception is the practice by which one exception is encapsulated into another:

    class MylibError(Exception):
        """Generic exception for mylib"""
        def __init__(self, msg, original_exception):
            super(MylibError, self).__init__(msg + (": %s" % original_exception))
            self.original_exception = original_exception
    
    try:
        requests.get("http://example.com")
    except requests.exceptions.ConnectionError as e:
         raise MylibError("Unable to connect", e)
    

    This makes sense when writing a library which leverages other libraries. If a library uses requests and does not encapsulate requests exceptions into its own defined error classes, it will be a case of layer violation. Any application using your library might receive a requests.exceptions.ConnectionError, which is a problem because:

    1. The application has no clue that the library was using requests and does not need/want to know about it.
    2. The application will have to import requests.exceptions itself and therefore will depend on requests – even if it does not use it directly.
    3. As soon as mylib changes from requests to e.g. httplib2, the application code catching requests exceptions will become irrelevant.

    The Tooz library is a good example of wrapping, as it uses a driver-based approach and depends on a lot of different Python modules to talk to different backends (ZooKeeper, PostgreSQL, etcd…).
    Therefore, it wraps exception from other modules on every occasion into its own set of error classes. Python 3 introduced the raise from form to help with that, and that’s what Tooz leverages to raise its own error.

    It’s also possible to encapsulate the original exception into a custom defined exception, as done above. That makes the original exception available for inspection easily.

    Catching and logging

    When designing exceptions, it’s important to remember that they should be targeted both at humans and computers. That’s why they should include an explicit message, and embed as much information as possible. That will help to debug and write resilient programs that can pivot their behavior depending on the attributes of exception, as seen above.

    Also, silencing exceptions completely is to be considered as bad practice. You should not write code like that:

    try:
        do_something()
    except Exception:
        # Whatever
        pass
    

    Not having any kind of information in a program where an exception occurs is a nightmare to debug.

    If you use (and you should) the logging library, you can use the exc_info parameter to log a complete traceback when an exception occurs, which might help debugging on severe and unrecoverable failure:

    try:
        do_something()
    except Exception:
        logging.getLogger().error("Something bad happened", exc_info=True)
    

    If you often forget on how to setup the logging library, you should check out daiquiri.

    Further reading

    If you understood everything so far, congratulations, you might be ready to handle exception in Python! If you want to have a broader scope on exceptions and what Python misses, I encourage you to read about condition systems and discover the generalization of exceptions – that I hope we’ll see in Python one day!

    I hope this will help you building better libraries and application. Feel free to shoot any question in the comment section!

    List of built-in exceptions in Python 3.

    Base Classes

    These exceptions are generally used as base classes for other exceptions.

    Exception Description
    BaseException The base class for all built-in exceptions. It is not meant to be directly inherited by user-defined classes (for that, use Exception below).
    Exception All built-in, non-system-exiting exceptions are derived from this class. All user-defined exceptions should also be derived from this class.
    ArithmeticError The base class for built-in exceptions that are raised for various arithmetic errors. These are: OverflowError, ZeroDivisionError, FloatingPointError.
    BufferError Raised when a buffer related operation cannot be performed.
    LookupError The base class for exceptions that are raised when a key or index used on a mapping or sequence is invalid. These are: IndexError and KeyError.

    Concrete Exceptions

    These are the exceptions that are usually raised.

    Exception Description
    AssertionError Raised when an assert statement fails.
    AttributeError

    Raised when an attribute reference or assignment fails.

    EOFError Raised when the input() function hits an end-of-file condition (EOF) without reading any data.
    FloatingPointError Raised when a floating point operation fails.
    GeneratorExit Raised when a generator or coroutine is closed. Technically, this is not an error, and the GeneratorExit exception directly inherits from BaseException instead of Exception.
    ImportError Raised when the import statement fails when trying to load a module. This exception is also raised when the from in from ... import has a name that cannot be found.
    ModuleNotFoundError A subclass of ImportError which is raised by import when a module could not be located. This exception is also raised when None is found in sys.modules.
    IndexError Raised when a sequence subscript is out of range.
    KeyError Raised when a mapping (dictionary) key is not found in the set of existing keys.
    KeyboardInterrupt Raised when the user hits the interrupt key (typically Control-C or Delete).
    MemoryError Raised when an operation runs out of memory but the situation may still be rescued (by deleting some objects).
    NameError Raised when a local or global name is not found. This applies only to unqualified names.
    NotImplementedError This exception is derived from RuntimeError. In user defined base classes, abstract methods should raise this exception when they require derived classes to override the method, or while the class is being developed to indicate that the real implementation still needs to be added.
    OSError() This exception is raised when a system function returns a system-related error, including I/O failures such as «file not found» or «disk full».
    OverflowError Raised when the result of an arithmetic operation is too large to be represented.
    RecursionError This exception is derived from RuntimeError. It is raised when the interpreter detects that the maximum recursion depth is exceeded.
    ReferenceError Raised when a weak reference proxy, created by the weakref.proxy() function, is used to access an attribute of the referent after it has been garbage collected.
    RuntimeError Raised when an error is detected that doesn’t fall in any of the other categories.
    StopIteration Raised by the next() function and an iterator’s __next__() method to signal that there are no further items produced by the iterator.
    StopAsyncIteration Must be raised by __anext__() method of an asynchronous iterator object to stop the iteration.
    SyntaxError Raised when the parser encounters a syntax error.
    IndentationError Base class for syntax errors related to incorrect indentation. This is a subclass of SyntaxError.
    TabError Raised when indentation contains an inconsistent use of tabs and spaces. This is a subclass of IndentationError.
    SystemError Raised when the interpreter finds an internal error, but it’s not serious enough to exit the interpreter.
    SystemExit This exception is raised by the sys.exit() function, and (when it is not handled) causes the Python interpreter to exit.
    TypeError Raised when an operation or function is applied to an object of inappropriate type.
    UnboundLocalError Raised when a reference is made to a local variable in a function or method, but no value has been bound to that variable. This is a subclass of NameError.
    UnicodeError Raised when a Unicode-related encoding or decoding error occurs. It is a subclass of ValueError.
    UnicodeEncodeError Raised when a Unicode-related error occurs during encoding. It is a subclass of UnicodeError.
    UnicodeDecodeError Raised when a Unicode-related error occurs during encoding. It is a subclass of UnicodeError.
    UnicodeTranslateError Raised when a Unicode-related error occurs during encoding. It is a subclass of UnicodeError.
    ValueError Raised when a built-in operation or function receives an argument that has the right type but an inappropriate value, and the situation is not described by a more precise exception.
    ZeroDivisionError Raised when the second argument of a division or modulo operation is zero.

    OS Exceptions

    These exceptions are subclasses of OSError. They get raised depending on the actual system error code.

    Exception Description
    BlockingIOError Raised when an operation would block on an object (e.g. socket) set for non-blocking operation.
    ChildProcessError Raised when an operation on a child process failed.
    ConnectionError A base class for connection-related issues.
    BrokenPipeError A subclass of ConnectionError, raised when trying to write on a pipe while the other end has been closed, or trying to write on a socket which has been shutdown for writing.
    ConnectionAbortedError A subclass of ConnectionError, raised when a connection attempt is aborted by the peer.
    ConnectionRefusedError A subclass of ConnectionError, raised when a connection is reset by the peer.
    FileExistsError Raised when trying to create a file or directory which already exists.
    FileNotFoundError Raised when a file or directory is requested but doesn’t exist.
    InterruptedError Raised when a system call is interrupted by an incoming signal.
    IsADirectoryError Raised when a file operation is requested on a directory.
    NotADirectoryError Raised when a directory operation is requested on something which is not a directory.
    PermissionError Raised when trying to run an operation without the adequate access rights.
    ProcessLookupError Raised when a given process doesn’t exist.
    TimeoutError Raised when a system function timed out at the system level.

    Warnings

    The following exceptions are used as warning categories.

    Exception Description
    Warning Base class for warning categories.
    UserWarning Base class for warnings generated by user code.
    DeprecationWarning Base class for warnings about deprecated features.
    PendingDeprecationWarning Base class for warnings about features which will be deprecated in the future.
    SyntaxWarning Base class for warnings about dubious syntax.
    RuntimeWarning Base class for warnings about dubious runtime behavior.
    FutureWarning Base class for warnings about constructs that will change semantically in the future.
    ImportWarning Base class for warnings about probable mistakes in module imports.
    UnicodeWarning Base class for warnings related to Unicode.
    BytesWarning Base class for warnings related to bytes and bytearray.
    ResourceWarning Base class for warnings related to resource usage.

    Exceptions refer to the events of errors experienced when executing a program. This Python Exceptions tutorial will overview different exceptions in Python and explain how to catch and mitigate them.

    Table of contents

    What are the exceptions in Python?

    Exceptions are events of failure in your Python code that result from database corruption, broken network connectivity, corrupted data, memory exhaustion, and unsupported user inputs. The purpose of every developer is to catch and mitigate such exceptions to ensure that the final program runs smoothly.

    If an exception occurs when an application runs, there is a risk of losing data, corrupting existing data, or even causing the application to crash.

    Python allows developers to handle these exceptions using pre-defined exceptions and structured exception handling.

    For example, it is always possible to predict the possible error in a Python program and work around it by prompting the user to use the correct input, default value or alternate a program execution flow. 

    The difference between syntax errors and exceptions in Python

    Syntax errors and exceptions in Python refer to unwanted conditions when executing a program.

    Syntax error refers to an error that terminates the execution of a program due to the use of the wrong Python syntax in the code.

    The wrong syntax comprises wrong naming styles, incorrect Python keywords, and invalid program structure.

    Let’s take a look at the example below to illustrate the syntax error:

    age = 18
    def check_age(age):
        if age >= 18
            print("Individual is an adult")

    If you try to execute the program above, you’ll get the following error message:

      File "syntax_error_example.py", line 4
        if age >= 18
                   ^
    SyntaxError: invalid syntax

    On the other hand, exceptions refer to errors in executing a program, even when a statement is syntactically correct.

    If the developer handles exceptions in the code, they do not stop the program’s execution but can lead to a change in the normal flow of the program execution.

    As we’ve mentioned, it is possible to handle exceptions in your Python code so they might not be fatal and might not stop Python program execution.

    We’ll take a look at how to handle exceptions later, but for now, let’s take a look at what happens if we’re not handling potentially dangerous situations in the code:

    x = "test"
    for i in range(x):
        print(i)

    Execution of the code block above will lead to the following error message and terminate program execution:

    Traceback (most recent call last):
      File "exception_example_1.py", line 3, in <module>
        for i in range(x):
    TypeError: 'str' object cannot be interpreted as an integer

    Python3 Exception Handling

    Now, it’s time to look at how to handle exceptions in Python.

    Try block syntax in Python

    To handle exceptions in Python, you need to use a try-except block, which has the following syntax:

    try:
        statement(s)
    except [exception_class]:
        statement(s)
    else:
        statement(s)
    finally:
        statement(s)

    Here’s how these clauses work:

    • The try clause runs the block of code where an error is expected to occur.
    • except clause used to define the type of exception expected from the try block of code.
    • If there’s no exception captured, the else statemetns block is executed
    • finally statements are always to be executed regardless of any exceptions caught in the try clause

    Catching a single exception in Python

    Python allows you to handle any exceptions.

    For example, let’s take a look at a program that prompts the user to enter a number, and when the program cannot convert the number to an integer, it raises a ValueError exception:

    for i in range(5):
        x = input("Type in a number: ")
        try:
            number = int(x)
        except ValueError:
            print("The value you entered ({}) cannot be converted to an integer".format(x))

    Now, let’s try to execute our program:

    Type in a number: uytfd
    The value you entered (uytfd) cannot be converted to an integer
    Type in a number: 5656
    Type in a number: 435
    Type in a number: dfdf
    The value you entered (dfdf) cannot be converted to an integer
    Type in a number: shs
    The value you entered (shs) cannot be converted to an integer

    If the user is typing something wrong, the try block will try to catch an exception by checking the exception classes provided in the except clause.

    If an exception doesn’t match any declared exceptions in the except clause, Python will stop program execution with the message unhandled exception.

    Keep in mind: when handling exceptions in except blocks, a base class type will catch any raised type of its subclasses. For example, the ArythmeticError exception class will catch OverflowError, FloatingPointError, and ZeroDivisionError exceptions.

    Catching multiple exceptions in Python

    A try clause can have to have several except clauses to catch different types of exceptions for the same block of code:

    for i in range(5):
        try:
            x = int(input("Type in a number: "))
        except (ValueError, TypeError, NameError):
            print("One of the above exceptions was captured during execution")

    Here’s an execution output:

    Type in a number: 675
    Type in a number: jgd
    One of the above exceptions wa captured during execution
    Type in a number: fg
    One of the above exceptions wa captured during execution
    Type in a number: 56
    Type in a number: 98

    In addition to that, it is possible to provide several except clauses to capture multiple exceptions:

    for i in range(2):
        user_input = input("Type in a number: ")
        try:
            x = int(user_input)
            y = set()
            y[1] = x
        except ValueError:
            print("The value you entered ({}) cannot be converted to an integer".format(user_input))
        except TypeError:
            print("You can not modify sets!!!")
    print("Program execution finished")

    Now, let’s try to execute the program above:

    Type in a number: asd
    The value you entered (asd) cannot be converted to an integer
    Type in a number: 1
    You can not modify sets!!!
    Program execution finished

    Even if we provide a valid value, we still have an error in the code, which was caught by the second except clause.

    Catching all exceptions in Python

    Sometimes we do not know what exception we can get during the code execution, but we need to catch the error and continue the execution flow.

    In that case, you can use except clause without providing an exception name, but it is not recommended to hide any issues in the code block.

    However, if you have a strong need, it is possible to catch any exception:

    import os
    path = "/not/existing/path"
    try:
        for file in os.listdir(path):
            f = open(os.path.join(path, file))
    except ValueError:
        print("Catching ValueError")
    except:
        print("Unexpected error happened")
    print("Program execution finished")

    Here’s the execution output:

    Unexpected error happened
    Program execution finished

    Using the “else” clause in the “try” block

    If you’d like to know if the code block has been executed without any errors, you can use else statement after the except clauses:

    for i in range(2):
        x = input("Type in a number: ")
        try:
            number = int(x)
        except ValueError:
            print("The value you entered ({}) cannot be converted to an integer".format(x))
        else:
            print("Code block executed without issues")
    print("Program execution finished")

    Program execution result:

    Type in a number: asf
    The value you entered (asf) cannot be converted to an integer
    Type in a number: 1
    Code block executed without issues
    Program execution finished

    Getting access to the exception class in Python

    If you need to get access to the exception class during the exception-handling process, you can do it by using as keyword in the except clause:

    try:
        a = 2/0
    except Exception as error:
        print(f'Exception info: {error.__doc__}')

    Here’s an expected output:

    Exception info: Second argument to a division or modulo operation was zero.

    The difference between else and finally in Python

    Lastly, let’s illustrate how else and finally clauses are working:

    for i in [0, 1]:
        try:
            result = 2 / i
        except ZeroDivisionError:
            print("Division by zero")
        else:
            print(f'Division result: {result}')
        finally:
            print("Executing finally clausen")
    print("Program execution finished")

    Here’s an execution output:

    Division by zero
    Executing finally clause
    Division result: 2.0
    Executing finally clause
    Program execution finished

    As you can see from the program execution, Python always executes the finally clause statements. At the same time, Python runs the else clause statements only when try block executed without any errors.

    Such behavior allows using the finally clause to define clean-up actions such as closing sockets, file descriptors, disconnecting from the database, etc.

    Your Python code should have these cleanup actions and execute them at all times, irrespective of the circumstances.

    How to catch SyntaxErrorexception in Python

    It is hard to catch the SyntaxError exception, but it is still possible if the SyntaxError is thrown out of an evalexec, or import statements:

    try:
        import my_module
    except SyntaxError:
        print("Syntax error in my_module")
    print("Program execution finished")

    Now, if the code in my_module Python module contains syntax errors, program execution will not break:

    Syntax error in my_module
    Program execution finished

    Raising exceptionsin Python

    You have an opportunity not only to catch and workaround exceptions but also to raise them. So, if you’d like to throw an error in Python, use the raise keyword followed by the error or exception type.

    A common example of when you need this is implementing a manager class that allows users to allocate a network from a certain IP pool.

    If the manager can’t allocate the network, it makes sense to create a user-defined exception and raise it when the event occurs.

    To raise an exception in Python, you need to use raise statement.

    The exception you can raise can be any class that derives from an Exception.

    A python program implicitly instantiates the constructor by passing an exception class with no arguments, for example:

    raise TypeError

    As soon as Python runs the statement above, it will produce the following error message:

    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError

    Re-raising exceptions in Python

    In some cases, you may need to re-raise an exception that you’re capturing with try-except block.

    That’s possible by using a raise statement without providing an exception class:

    try:
        raise TypeError(10.578)
    except TypeError:
        print('A float number was not captured!')
        raise

    The code above will not only raise an exception but also print the reason for that exception:

    A float number was not captured!
    Traceback (most recent call last):
      File "rerising_exceptions.py", line 2, in <module>
        raise TypeError(10.578)
    TypeError: 10.578

    Chaining exceptions in Python

    Chaining exceptions is useful when you need to transform exceptions.

    You can specify an optional from keyword in the raise statement that allows you to re-raise the exception and change its type:

    def example():
       try:
         x = input("Type in a number: ")
         number = int(x)
       except ValueError as e:
         raise RuntimeError('User input parsing error occurred') from e
        
    example()

    Here’s an execution output:

    Type in a number: asd
    Traceback (most recent call last):
      File "multiple_except.py", line 4, in example
        number = int(x)
    ValueError: invalid literal for int() with base 10: 'asd'
    The above exception was the direct cause of the following exception:
    Traceback (most recent call last):
      File "multiple_except.py", line 8, in <module>
        example()
      File "multiple_except.py", line 6, in example
        raise RuntimeError('A parsing error occurred') from e
    RuntimeError: A parsing error occurred

    Built-In Python exceptions

    Most of the built-in exceptions are inheriting the BaseException class. Python interpreter usually generates these exceptions from built-in functions to help developers identify the root cause of an error during Python program execution.

    You can inherit built-in exception classes to define new exceptions. All Python developers are encouraged to derive new exceptions from the Exception class or one of its subclasses but not from the BaseException class.

    Base exception classes in Python

    The tree of base exception classes provides Python developers with lots of standard exceptions. In this part of the article, we’ll review the purpose of Python3 exceptions.

    • BaseException is the base class for all the built-in exceptions. Python developers should not directly inherit this class to define any custom exception classes. This class creates a string representation of the exception by defining the str() method and its arguments. If there are no arguments Python will return an exception with an empty string.
      • GeneratorExit Python throws this exception when a coroutine or generator is closed. It inherits from the BaseException but not the Exception class because it is not an error.
      • KeyboardInterrupt – When a user hits the interrupt key such as Delete or Control+C, this error exception is raised.
      • SystemExit – When the sys.exit() function is called, this exception is raised. In addition, calling this function indicates that clean-up handlers should be executed, that is, the finally clauses of try statements.
      • Exception – is a base class for all built-in non-system-exiting exceptions and user-defined exceptions
    Exceptions handling in Python - BaseException
    • ArithmeticError is the base exception class for arithmetic errors such as FloatingPointError, ZeroDivisionError, and OverflowError.
      • FloatingPointError – you can catch this exception when the operation of a floating-point value fails. However, the exception is always defined and it can only be raised if the WANT_SIGFPE_HANDLER symbol is defined in the pyconfig.h file.
      • ZeroDivisionError happens when second argument of the division or modulo operation equals zero
    Exceptions handling in Python - ArithmeticError
    • LookupError defines a base class for IndexError and KeyError exceptions that raised by Python when developer is trying to manipulate non-existing or is invalid index or key values at sequence or mapping.
      • IndexError exception happens when a referenced sequence is out of range
      • KeyError you can catch this exception if a mapping key not found in the set of existing keys
      • OverflowError – this exception happens when the results from an arithmetic operation are out of range and also if integers are out of a required range
    Exceptions handling in Python - LookupError

    Concrete exceptions in Python

    Concrete exceptions in Python are build-in exceptions that inherited directly from the Exception class.

    Exceptions handling in Python - Exception

    Here’s a quick description of all concrete exceptions:

    • BufferError – Python throws this exception when a buffer-related operation fails to execute correctly
    • AssertionError is raised when an assert statement fails in Python code
    • ValueError – you can catch this exception when a built-in function or operation receives the correct type of argument but with an invalid value
      • UnicodeError – This is a subclass of ValueError and is raised when a Unicode decoding or encoding error is captured.
    Exceptions handling in Python - ValueError
    • TypeError – Python throws this exception when developer apply an inappropriate type object to a function or an operation. A string that gives the details related to the mismatch is returned by this exception.
    • SystemError – Python throws this exception when the interpreter encounters an internal error.
    • StopIteration – The built-in function next() and the iterator’s __next__() method raise this exception to indicate that all items are produced by the iterator.
    • RuntimeError – raises when no other exception applies. A string is returned with the details of the actual problem encountered during execution.
      • RecursionError – Derived from the RuntimeError and is raised when the maximum recursion depth has been exceeded.
      • NotImplementedError – The exception is derived from the RuntimeError and is raised when derived classes override the abstract methods in user-defined classes.
    Exceptions handling in Python - RuntimeError
    • SyntaxError – you can catch this exception when an interpreter encounters wrong syntax. A syntax error can be experienced in an import statement or when reading a standard input or when calling the builtin function eval() or exec().
    Exceptions handling in Python - SyntaxError
    • ReferenceError – Python throws this exception when a weak reference proxy to accesses an attribute of the reference after the garbage collection.
    • AttributeError – you’re getting this exception whenever the assignment or reference of an attribute fails. This can happen because the referred attribute does not exist.
    • MemoryError – when Python runs out of memory it throws this exception
    • EOFError – The EOFError is raised if the built-in functions such as input() encounters an end-of-file (EOF) condition without reading any data. For instance, in case the readline() builtin function encounters an EOF, it returns an empty string.
    • ImportError – Raised when the import statement fails to load a module or when the from list in from import has a name that does not exist.
      • ModuleNotFoundError – It is a subclass of the ImportError and is raised when a module could not be found. In addition to that, if None is found in sys.modules the exception can also be raised.
    Exceptions handling in Python - ImportError
    • NameError – The exception is raised when a global or local name is not found.
      • UnboundLocalError – This exception is raised when a reference is made to a local variable in a method or a function but there is no value bound to that variable.
    Exceptions handling in Python - NameError
    • OSError([arg]) – Whenever a system function returns a system-related error such as I/O failures including “disk full” or “file not found” errors.
      • FileNotFoundError – Raised when a requested file directory or file does not exist.
      • FileExistsError – This exception is raised when attempting to create an already existing file or a directory.
      • TimeoutError – Raised when a system function timed out at the system level.
      • PermissionError – Raised when attempting to run an application without the required access rights.
      • ConnectionError – This is the base class for connection related issues and the subclasses are:
        • BrokenPipeError – Raised when attempting to write on a pipe closed on the other end. Also when attempting to write on a shut down socket.
        • ConnectionResetError – The exception is raised when a peer resets a connection.
        • ConnectionAbortedError – Raised when a peer aborts a connection attempt.
        • ConnectionRefusedError – Raised if a peer refuses a connection attempt.
      • ProcessLookupError – It gets raised in case a specified process does not exist.
      • InterruptedError – The exception is raised when a system class is interrupted by an incoming signal. In Python 3.5+, Python retries system calls whenever a system call is interrupted.
      • IsADirectoryError – It is raised when a file operation such as os.remove() is requested on a directory.
      • NotADirectoryError – Raised when a directory operation such as os.listdir() is requested on an argument that is not a directory.
      • ChildProcessError – Gets raised when a child process operatio fails.
      • BlockingIOError – This error is raised when an operation would block on an object set for non-blocking operation.
    Exceptions handling in Python - OSError

    Warnings in Python

    Developers typically use warning messages when they need to alert the user about some important condition in a program. Usually, such a condition doesn’t raise an exception or terminate the program. A good example might be to print a warning when a program uses an obsolete Python module.

    Here’s a list of built-in Python warnings:

    • FutureWarning – This is the base class of warnings about deprecated features.
    • BytesWarning – Base class for warning related to bytearray and bytes.
    • SyntaxWarning – For dubious syntax, this is the base class of such warnings.
    • ImportWarning – Base class for warning related to probable mistakes in module imports.
    • Warning – Base class for warning categories.
    • UserWarning – This is the base class for warnings that have been generated by the user code.
    • ResourceWarning – Base class for warnings associated with resource usage. 
    • PendingDeprecationWarning – This is the base class for warnings related to obsolete features that are expected to be deprecated in the future. For already active deprecation the DeprecationWarning is used.
    • DeprecationWarning – Base class for the warning associated with deprecated features.
    • UnicodeWarning – Base class for warning related to Unicode.
    Exceptions handling in Python - Warning

    User-defined exceptions in Python

    You can inherit from any built-in exception class to create your own exception type.

    User-defined exceptions allow us to display more relevant and detailed information when an exception occurs during program execution, for example:

    class CustomError(Exception):
        pass
    raise CustomError('My custom error')

    Here’s the program output:

    Traceback (most recent call last):
      File "multiple_except.py", line 4, in <module>
        raise CustomError('My custom error')
    __main__.CustomError: My custom error

    Customizing exception classes in Python

    If you’d like to implement more meaningful exception messages in your Python program, you can do it by implementing an exception class constructor:

    ALLOWED_CAR_COLOURS = ['black', 'red', 'green']
    class IncorrectCarColourException(Exception):
        """Exception raised for errors in the car colour input.
        Attributes:
            colour -- car colour
        """
        def __init__(self, colour):
            self.colour = colour
            self.message = f'''
                {self.colour} car colour is not allowed.
                Allowed values are {ALLOWED_CAR_COLOURS}
            '''
            super().__init__(self.message)
    
    car_color = input("Enter car colour: ")
    if not car_color in ALLOWED_CAR_COLOURS:
        raise IncorrectCarColourException(car_color)

    Here’s an execution example:

    Enter car colour: white
    Traceback (most recent call last):
      File "multiple_except.py", line 22, in <module>
        raise IncorrectCarColourException(car_color)
    __main__.IncorrectCarColourException:
                white car colour is not allowed.
                Allowed values are ['black', 'red', 'green']

    Summary

    We have seen different types of exceptions, both built-in and user-defined ones. In addition to that, we have reviewed specific exceptions and errors that occur to raise these exceptions. The article has a detailed explanation of how to handle and raise exceptions in a Python program.

    Понравилась статья? Поделить с друзьями:
  • Python 401 error
  • Pytest error unrecognized arguments
  • Pytest assert error
  • Pyscripter could not load a python engine ошибка
  • Pyqtdeploy build there was an error reading the project file