· Hakan Çelik · Python · 5 dk okuma

Error Handling in Python

In the topics covered so far we never talked about errors, how to catch them, or how to continue execution based on the error encountered. This is an important topic and you will learn it here.

Error Handling in Python

Catching Errors in Python

In the topics covered so far we never talked about errors, how to catch them, or how to continue execution based on the error encountered — but this is an important topic and you will learn it here.

Here is a small example:

get_n = float(input("Enter a number >> "))
result = 10 / get_n
print(f"result {result}")

What happens if the user enters 0 instead of 1 or 2? An error occurs and our program does not produce the result we want. You could control the zero-entry case with if, or you can use Python’s error handling mechanism.

The script below shows how we find which error occurred:

try:
    1 / 0
except Exception as exc:
    print(f"Oh no! We caught a {exc.__class__.__name__} error")

Output:

Oh no! We caught a ZeroDivisionError error

As you can see, dividing a number by zero gives us ZeroDivisionError.

Catching Specific Errors

Try, Except

General Structure

try:
   # some code
   pass
except ValueError:
   # runs if a ValueError occurs
   pass
except (TypeError, ZeroDivisionError):
   # catching multiple errors at once
   # runs if TypeError or ZeroDivisionError occurs
   pass
except Exception:
   # runs if any other error occurs
   pass

Try, Except, As

The as keyword assigns the caught exception instance to a name.

General Structure 1

try:
   pass
except ValueError as error:
   # caught a ValueError — receive it as "error" and print it
   print(error)

General Structure 2

try:
   pass
except Exception as e:
   # any error caught — receive it as "e" and print it
   print(e)

Try, Except, Else

General Structure

try:
   pass
except:
   # runs if any error occurs
   pass
else:
    # runs if NO error occurred
    pass

Try, Except, Else, Finally

General Structure

try:
   pass
except:
   pass
else:
    pass
finally:
    # runs whether or not an error occurred
    pass

Creating Our Own Exception Class

To do this we use the Exception class and the raise keyword.

raise

raise is a keyword used to raise (trigger) any exception class.

Let us redo the example from the beginning:

class InputError(Exception):
    """An exception class for input errors.

    Attributes:
        expression -- input expression in which the error occurred
        message    -- explanation of the error
    """

    def __init__(self, expression, message):
        self.expression = expression
        self.message = message

input_ = float(input("Enter a number other than 0 >> "))
if input_ == 0:
    raise InputError(input_, "do not enter 0")

Result:

Traceback (most recent call last):
  File "myapp.py", line 28, in <module>
    raise InputError(input_, "do not enter 0")
__main__.InputError: (0.0, 'do not enter 0')

Now let us refine it and also catch the error we raise:

class InputError(Exception):
    def __init__(self, expression, message):
        self.expression = expression
        self.message = message

def get_input():
    input_ = float(input("Enter a number other than 0 >> "))
    if input_ == 0:
        raise InputError(input_, "do not enter 0")
    return input_

try:
    input_ = get_input()
except InputError as e:   # if the returned error is our InputError
    print(e)
else:
    print(input_)

Result:

Enter a number other than 0 >> 0
(0.0, 'do not enter 0')

Python Built-in Exceptions

ExceptionCause of Error
AssertionErrorRaised when an assert statement fails.
AttributeErrorRaised when attribute assignment or reference fails.
EOFErrorRaised when the input() function hits an end-of-file condition.
FloatingPointErrorRaised when a floating-point operation fails.
GeneratorExitRaised when a generator’s close() method is called.
ImportErrorRaised when an imported module is not found.
IndexErrorRaised when an index is out of range.
KeyErrorRaised when a key is not found in a dictionary.
KeyboardInterruptRaised when the user hits the interrupt key (Ctrl+C or Delete).
MemoryErrorRaised when an operation runs out of memory.
NameErrorRaised when a variable is not found in local or global scope.
NotImplementedErrorRaised by abstract methods.
OSErrorRaised when a system operation causes a system-related error.
OverflowErrorRaised when the result of an arithmetic operation is too large to be represented.
ReferenceErrorRaised when a weak reference proxy is used to access a garbage-collected referent.
RuntimeErrorRaised when an error does not fall under any other category.
StopIterationRaised by next() to indicate there are no further items to return.
SyntaxErrorRaised by the parser when a syntax error is encountered.
IndentationErrorRaised when there is incorrect indentation.
TabErrorRaised when indentation consists of inconsistent tabs and spaces.
SystemErrorRaised when the interpreter detects an internal error.
SystemExitRaised by sys.exit().
TypeErrorRaised when a function or operation is applied to an object of incorrect type.
UnboundLocalErrorRaised when a reference is made to a local variable that has no value bound to it.
UnicodeErrorRaised when a Unicode-related encoding or decoding error occurs.
UnicodeEncodeErrorRaised when a Unicode-related error occurs during encoding.
UnicodeDecodeErrorRaised when a Unicode-related error occurs during decoding.
UnicodeTranslateErrorRaised when a Unicode-related error occurs during translating.
ValueErrorRaised when a function gets an argument of the correct type but an improper value.
ZeroDivisionErrorRaised when the second operand of a division or modulo operation is zero.

The tree below shows which exception inherits from which:

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StopAsyncIteration
      +-- ArithmeticError
      |    +-- FloatingPointError
      |    +-- OverflowError
      |    +-- ZeroDivisionError
      +-- AssertionError
      +-- AttributeError
      +-- BufferError
      +-- EOFError
      +-- ImportError
      |    +-- ModuleNotFoundError
      +-- LookupError
      |    +-- IndexError
      |    +-- KeyError
      +-- MemoryError
      +-- NameError
      |    +-- UnboundLocalError
      +-- OSError
      |    +-- BlockingIOError
      |    +-- ChildProcessError
      |    +-- ConnectionError
      |    |    +-- BrokenPipeError
      |    |    +-- ConnectionAbortedError
      |    |    +-- ConnectionRefusedError
      |    |    +-- ConnectionResetError
      |    +-- FileExistsError
      |    +-- FileNotFoundError
      |    +-- InterruptedError
      |    +-- IsADirectoryError
      |    +-- NotADirectoryError
      |    +-- PermissionError
      |    +-- ProcessLookupError
      |    +-- TimeoutError
      +-- ReferenceError
      +-- RuntimeError
      |    +-- NotImplementedError
      |    +-- RecursionError
      +-- SyntaxError
      |    +-- IndentationError
      |         +-- TabError
      +-- SystemError
      +-- TypeError
      +-- ValueError
      |    +-- UnicodeError
      |         +-- UnicodeDecodeError
      |         +-- UnicodeEncodeError
      |         +-- UnicodeTranslateError
      +-- Warning
           +-- DeprecationWarning
           +-- PendingDeprecationWarning
           +-- RuntimeWarning
           +-- SyntaxWarning
           +-- UserWarning
           +-- FutureWarning
           +-- ImportWarning
           +-- UnicodeWarning
           +-- BytesWarning
           +-- ResourceWarning

References

Share:
Back to Blog

Related Posts

View All Posts »
Understanding Python Classes

Understanding Python Classes

Python · 2 dk

In Python, everything is an object and every object has a type — including primitives, functions, and classes themselves. type() and __class__ reveal this relationship.

Run Methods Order In Python

Run Methods Order In Python

Python · 2 dk

Which method runs when in Python metaclasses? The execution order of __prepare__, __new__, __init__, and __call__ during class definition and instance creation.