Exception handling is a process of responding to exceptions that occur during the execution of a program. Without exception handling, programs would not be able to recover from errors.
In normal situations, whenever an exception is encountered, the program comes to an immediate stop. Exception handling allows us to catch the exception, perform a corrective action if necessary, and then continue with the program's execution from the point the exception was raised. This prevents the program from abruptly halting.
Python offers three keywords for use in handling exceptions, these are, try, except and finally. The three keywords provides an organized, structured way to handle the exceptions and continue running the program.
Try and except blocks
The try
and except
blocks are used together to "catch" exceptions as they are raised.
What simply goes on is that, we put the statement(s) that can raise an exception in the try
block and then we put the corrective statements under the except
block. If the statement(s) under the try
block raises an exception, the exception object is passed to the except
block as the statements under its block gets executed.
In the above example, we used undefined variables, a, b, and c. Under normal circumstances, a NameError
would have been raised but by using the try except block, we effectively catch the error and respond accordingly.
Used as above, the except
block acts as a catchall block. It responds to any type of an exception that will be raised except the SyntaxError which can't be handled except when executing code dynamically using the eval(). or the exec() functions.
Did we really "catch" the exception?
In our previous example, we used the try-except blocks without really caring what exception was being raised. However the except block is capable of getting the specific exception that was raised.
Remember that, ultimately, all exceptions are subclasses of the Exception
class. When we catch any exception, an Exception
object is passed to the except
block. We can then alias the exception raised using the "as" clause as shown below:
Handle the specific exception
In all the previous examples, we handled all exceptions at once. However this is a bad programming practice and should generally be avoided as it can lead to hard-to-debug errors.
The Pythonic way is to be as explicit as possible by handling only the exception that you expect to occur. We achieve this by simply using the except keyword followed by the exception that we want to catch.
In the above case we only handle the ZeroDivisionError
, any other exception that will occur in the try block will be raised as usual.
Multiple except blocks
You can have as many except blocks as necessary. This allows you to handle different kinds of errors that may occur in the same code. However, the try
block will be exited when the first exception is encountered
try: # statement(s) except IndexError: # statement(s) except ValueError: # statement(s)
copy
The else block
One feature about Python is that it allows the use of the else
block in some unexpected places this includes with for
and while
loops and now with the try
blocks.
The else
block when used with the try-except
blocks only gets executed if the try
block terminates successfully i.e no exception was raised inside the
block.
You can only have one else
block in a try-except arrangement and it should be placed after the try
and except
blocks
The 'finally' block
The finally
block executed gets regardless of whether the try block terminated successfully or an exception was raised.
The block should be placed as the last block after the try
, except
and else
blocks.
try: # Some statements.... except: # Handling of exception (if required) else: # execute if no exception is raised in the try block finally: # Some code .....(always executed)
copy
Note: Either the except
or the finally
block must be present for the try
block to work. A SyntaxError
will be raised otherwise.