Introduction
Python will let you know when you get your syntax wrong. It’ll immediately fail and not allow your program to run.
What about when your code has a different type of problem? Those are called exceptions, and they tend to be harder to catch. It’s up to you to recognize situations where hey might come up and catch them to prevent your program from crashing altogether.
Imagine a scenario where you need user input. Do you want your program to crash every time a user mistypes something or enters something erroneous? That’s far from ideal. Since you know there could be a problem there, you can tell Python to look out for one, and recover gracefully.
Try and Except
When you know there’s a chance an exception will pop up, you ask Python to try the piece of code and look out for an exception. Take a look at it in the context of the number example from before.
try: number = int(input("Enter any number: ")) except: print("That didn't work…")
Now, instead of crashing, you program will continue, even if the user enters garbage.
You can also tell Python exactly what type of exception to look for. In this case, it would be a ValueError
.
try: number = int(input("Enter any number: ")) except ValueError: print("You didn't enter a number!")
If Python knows what type of exception it’s looking for, you can tell it how to respond accordingly.
Make Your Own
You can make your own exceptions by writing them as classes that inherit from the Exception
base class or any one of the other exception classes.
class NewException(Exception): pass
You have to build into your program how to use your custom exceptions.
Raising Exceptions
There is an option to manually raise exceptions with raise
.
try: raise NewException except NewException: print("It failed as planned!")
Multiple Excepts
If you’re expecting that there could be more than one exception, you can built multiples in with try
. Start off by making a couple of custom exceptions.
class ExceptionA(Exception): pass class ExceptionB(Exception): pass
Now, use them with try
.
try: raise ExceptionB except (ExceptionA, ExceptionB): print("It was either A or B")
Of course, that’s not the best because in a real scenario, you wouldn’t know which exception actually occurred.
Try using separate except clauses instead.
try: raise ExceptionB except ExceptionA: print("ExceptionA Occurred") except ExceptionB: print("ExceptionB Occurred") except: print("Something else happened…")
The third except
acts to catch any other exception. That’s the default behavior when a specific exception isn’t given.
Else and Finally
There are two additional clauses for handling what happens after exceptions are handled. They help your code respond to exceptions.
The else
clause allows you to run code only if an exception hasn’t been raised.
try: number = int(input("Enter any number: ")) except ValueError: print("You didn't enter a number!") else: print(number ** 2)
You only want to try performing an operation on the number if one is entered.
The finally
cause will run regardless of any exceptions. It will always run at the end of the try
block.
try: number = int(input("Enter any number: ")) except ValueError: print("You didn't enter a number!") else: print(number ** 2) finally: print("This will always run.")
Closing Thoughts
It’s important to understand what can go wrong with your programs. It’s just as important to know that thing will go wrong. By accounting for exceptions, you can make your code as stable as possible and not frustrate your users.
Exercises
- Create some code that raises an unhandled exception.
- Use a try block to handle that exception.
- Create a custom exception class
- Raise that custom exception in a try block.
- Create a try block with a piece of code that only runs if an exception isn’t raised.