Creating software is hard work. To make your software better, your application needs to keep working even when the unexpected happens. For example, let's say your application needs to pull information down from the Internet. What happens if the person using your application loses their Internet connectivity?
Another common issue is what to do if the user enters invalid input. Or tries to open a file that your application doesn't support.
All of these cases can be handled using Python's built-in exception handling capabilities, which are commonly referred to as the
In this article you will learn about:
Let's get starting by learning about some of the most common exceptions.
Python supports lots of different exceptions. Here is a shortlist of the ones that you are likely to see when you first begin using the language:
Exception- The base exception that all the others are based on
AttributeError- Raised when an attribute reference or assignment fails.
ImportError- Raised when an import statement fails to find the module definition or when a from ... import fails to find a name that is to be imported.
ModuleNotFoundError- A subclass of ImportError which is raised by import when a module could not be located
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 (normally
NameError- Raised when a local or global name is not found.
OSError- Raised when a function returns a system-related error.
RuntimeError- Raised when an error is detected that doesn’t fall in any of the other categories.
SyntaxError- Raised when the parser encounters a syntax error.
TypeError- Raised when an operation or function is applied to an object of inappropriate type. The associated value is a string giving details about the type mismatch.
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 such as IndexError.
ZeroDivisionError- Raised when the second argument of a division or modulo operation is zero.
For a full listing of the built-in exceptions, you can check out the Python documentation here:
Now let's find out how you can actually handle an exception when one occurs.
Python comes with a special syntax that you can use to catch an exception. It is known as the
This is the basic form that you will use to catch an exception:
try: # Code that may raise an exception goes here except ImportError: # Code that is executed when an exception occurs
You put code that you expect might have an issue inside the
try block. This might be code that opens a file or code that gets input from the user. The second block is known as the
except block. This code will only get executed if an
ImportError is raised.
When you write the
except without specifying the exception type, it is known as a bare exception. These are not recommended:
try: with open('example.txt') as file_handler: for line in file_handler: print(line) except: print('An error occurred')
The reason it is bad practice to create a bare except is that you don't know what types of exceptions you are catching. This can make figuring out what you did wrong more difficult. If you narrow the exception types down to the ones you expect, then the unexpected ones will actually make your application crash with a useful message.
At that point, you can decide if you want to catch that other condition or not.
Let's say you want to catch multiple exceptions. Here is one way to do that:
try: with open('example.txt') as file_handler: for line in file_handler: print(line) import something except OSError: print('An error occurred') except ImportError: print('Unknown import!')
This exception handler will catch two types of exceptions:
ImportError. If another type of exception occurs, this handler won't catch it and your code will stop.
You can rewrite the code above to be a bit simpler by doing this:
try: with open('example.txt') as file_handler: for line in file_handler: print(line) import something except (OSError, ImportError): print('An error occurred')
Of course, by creating a tuple of exceptions, this will obfuscate which exception has occurred. In other words, this code makes it harder to know which exception occurred.
What do you do after you catch an exception? You have a couple of options. You can print out a message like you have been in the previous examples. You could also log the message to a log file. Or if the exception is one that you know needs to stop the execution of your application, you can re-raise the exception.
Raising an exception is the process of forcing an exception to occur. You raise exceptions in special cases. For example, if the application gets into a bad state, you might raise an exception. You will also tend to raise exceptions after already handling the exception.
You can use Python's built-in
raise statement to raise an exception:
try: raise ImportError except ImportError: print('Caught an ImportError')
When you raise an exception, you can have it print out a custom message:
>>> raise Exception('Something bad happened!') Traceback (most recent call last): Python Shell, prompt 1, line 1 builtins.Exception: Something bad happened!
If you don't provide a message, then the exception would look like this:
>>> raise Exception Traceback (most recent call last): Python Shell, prompt 2, line 1 builtins.Exception:
Now let's learn about the exception object!
When an exception occurs, Python will create an exception object. You can examine the exception object by assigning it to a variable using the
>>> try: ... raise ImportError('Bad import') ... except ImportError as error: ... print(type(error)) ... print(error.args) ... print(error) ... <class 'ImportError'> ('Bad import',) Bad import
In this example, you assigned the
ImportError object to
error. Now you can use Python's
type() function to learn what kind of exception it was. This would allow you to solve the issue mentioned earlier in this article when you have a tuple of exceptions but you can't immediately know which exception you caught.
If you want to dive even deeper into debugging exceptions, you should look up Python's
There is more to the
try/except statement than just
except. You can add a
finally statement to it as well. The
finally statement is a block of code that will always get run even if there is an exception raised inside of the
You can use the
finally statement for cleanup. For example, you might need to close a database connection or a file handle. To do that, you can wrap the code in a
Let's look at a contrived example:
>>> try: ... 1 / 0 ... except ZeroDivisionError: ... print('You can not divide by zero!') ... finally: ... print('Cleaning up') ... You can not divide by zero! Cleaning up
This example demonstrates how you can handle the
ZeroDivisionError exception as well as add on clean up code.
But you can also skip the
except statement entirely and create a
>>> try: ... 1/0 ... finally: ... print('Cleaning up') ... Cleaning upTraceback (most recent call last): Python Shell, prompt 6, line 2 builtins.ZeroDivisionError: division by zero
This time you don't handle the
ZeroDivisionError exception, but the
finally statement's code block runs anyway.
There is one other statement that you can use with Python's exception handling and that is the
else statement. You can use the
else statement to execute code when there are no exceptions.
Here is an example:
>>> try: ... print('This is the try block') ... except IOError: ... print('An IOError has occurred') ... else: ... print('This is the else block') ... This is the try block This is the else block
In this code, no exception occurred, so the
try block and the
else blocks both run.
Let's try raising an
IOError and see what happens:
>>> try: ... raise IOError ... print('This is the try block') ... except IOError: ... print('An IOError has occurred') ... else: ... print('This is the else block') ... An IOError has occurred
Since an exception was raised, only the
try and the
except blocks ran. Note that the
try block stopped running at the
raise statement. It never reached the
print() function at all. Once an exception is raised, all the following code is skipped over and you go straight to the exception handling code.
Now you know the basics of using Python's built-in exception handling. In this article you learned about the following topics:
Learning how to catch exceptions effectively takes practice. Once you have learned how to catch exceptions, you will be able to harden your code and make it work in a much nicer way even when the unexpected happens.
Copyright © 2022 Mouse Vs Python | Powered by Pythonlibrary