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, inprint(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, inprint(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.
Exampletry: 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.