Python Exception Handling

Python Exception Handling thumbnail
3K
By Dhiraj 17 March, 2019

Exception handling is the mechanism to stop normal program flow during an exceptional condition of the program flow. In this tutorial, we will be discussing the exception handling in Python with keywords try, except, finally and raise. We will also discuss the exception hierarchy, ways to extract messages from the exception object along with practices to use exception hierarchy to catch specific exceptions.

In Python, we raise an exception to interrupt the normal program flow and handle the exception to resume the control flow to exception handler. If we fail to handle the exception, the unhandled exception terminates the program and hence it is required to handle exception.

Exception objects contain information about the exceptional event containing where and why the exception has occurred.

Why Exception Handling is Required

Let us demonstrate a simple exception case in Python. Below is a function definition that accepts an argument and returns an integer value out of it.

def test(x):
    return int(x)


print(test("100")) # First test
print(test('abc')) # Second test
print(test("200")) # Third test

When we run this program, the first test successfully executes and 100 is printed in the console. But the second test will fail as the object "abc" can not be converted to int and an exception was raised by int() constructor and we got a trace back for int() call as below:

Traceback (most recent call last):
100
  File "D:/workspace/python/examples/test.py", line 6, in 
    print(test('abc'))
  File "D:/workspace/python/examples/test.py", line 2, in test
    return int(x)
ValueError: invalid literal for int() with base 10: 'abc'

Now, if you look into the output, the first test was executed successfully and 100 was printed in the console. Then the exception occurred and the Third test case was not executed as the exception terminates the control flow and the program terminated abnormally. Since, we did not have a proper exception handler, the exception propagated and the execution stopped abnormally.

Hence, an exception handling is required to control the normal flow of program execution.

If you inspect the traceback, ValueError referrred in the traceback is the type of exception raised and invalid literal for int() with base 10: 'abc' is the exception message that is displayed in the console.

Handling Exception with try and except keyword

try is a keyword in Python. Any code that could raise an exception is put inside try block and except block performs the exception handling for an event for which an exception is raised. Below is the modification that we have made in above code.

def test(x):
    return int(x)


try:
    print(test('abc'))
except ValueError:
    print(-1)
print(test("100"))

Now, when we run the above program, we can see output as below in the console. The ValueError exception was raised but the same was handled. Hence, our program did not shut down and the later statement was executed successfully.

Output
-1
100

As we have already handled the ValueError exception, let us try with below arguments now.

...
...
try:
    print(test([1, 3, 5]))
except ValueError:
    print(-1)
	
Output
Traceback (most recent call last):
  File "D:/workspace/python/examples/test.py", line 6, in 
    print(test([1, 3, 5]))
  File "D:/workspace/python/examples/test.py", line 2, in test
    return int(x)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'list'

If we lok into the console, this time we got TypeError which is again a different type of exception. Again, this can be handled as below:

def test(x):
    return int(x)


try:
    print(test([1, 3, 5]))
except (ValueError, TypeError):
    print(-1)
print(test("100"))

Programmer Errors

Errors such as IdentationError, SyntaxError, NameError are those errors which can also cause exceptions. But these exceptions need not be catched with except block. Rather, these exceptions are checked by IDE during program development and need to be fixed as per the alerts given by IDE.

try:
print(test([1, 3, 5]))
except (ValueError, TypeError):
    print(-1)
Output
  File "D:/workspace/python/examples/test.py", line 6
    print(test([1, 3, 5]))
        ^
IndentationError: expected an indented block

Extracting Specific Error Messages from Exception Object

There are ways with which we can extract error messages from the exception raised such as ValueError or TypeError by using as keyword. The "as" keyword is used to assign the error to a variable so that the error can be investigated more thoroughly later on in the code.

def test(x):
    return int(x)


try:
    print(test("abc"))
except (ValueError, TypeError) as e:
    print("Error during conversion : " + str(e))
print(test("100"))
Output
Error during conversion : invalid literal for int() with base 10: 'abc'
100

Re-raising Exception in Python

We use raise keyword from except block to re-raise an exception in Python. Below is an example. Also, we can also use raise keyword to ground the actual error and raise our custom error if any.

def test(x):
    return int(x)


try:
    print(test("abc"))
except (ValueError, TypeError) as e:
    print("Error during conversion : " + str(e))
    raise
print(test("100"))
def test(x, y):
    if y == 0:
        raise ValueError("The divisor can not be 0")
    return x / y


try:
    print(test(10, 0))
except ValueError as e:
    print(str(e))

finally block in Python

finally block is mainly used for resource clean up such as closing a file peration or a network connection. The code inside finally block executes whether an exception occurs or not. The finally block follows try or excpet block

try:
    f = open("test.txt")
    f.write("test content")
except FileNotFoundError as e:
    print("except bock executed")
    print(str(e))
finally:
    print("Finally block executed.")
    #Free up resources

Output
except bock executed
[Errno 2] No such file or directory: 'test.txt'
Finally block executed.

Multi-Level Exception Handling

As per the docs, when an exception occurs, Python searches for the first exception clause which matches the exception type that occurred. It doesn’t need to be an exact match. If the exception clause represents a base class of the raised exception, then Python considers that exception clause to be a match and the code block of that except block is executed and hence we won't be able to catch specific exception and it won't be much helpful.

Example
try:
    5 / 0
except Exception as e:
    print("Exception")
# unreachable code!
except ZeroDivisionError as e:
    print("ZeroDivisionError")

You can visit the docs for the list of exception hierarchy in Python.

Conclusion

In this article, we learnt about exception handling in Python with keywords such as try, except, raise and finally. We discussed about different ways to exract messages from the exception and looked into different buil-in exception hierarchy in Python.

Share

If You Appreciate This, You Can Consider:

We are thankful for your never ending support.

About The Author

author-image
A technology savvy professional with an exceptional capacity to analyze, solve problems and multi-task. Technical expertise in highly scalable distributed systems, self-healing systems, and service-oriented architecture. Technical Skills: Java/J2EE, Spring, Hibernate, Reactive Programming, Microservices, Hystrix, Rest APIs, Java 8, Kafka, Kibana, Elasticsearch, etc.

Further Reading on Python