• 8 hours
  • Medium

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 8/30/22

Manage Exceptions With Python

Discover How to Manage Exceptions With Python

As you saw in the chapter “Learn to Understand What Python Tells You,” exceptions are bugs that appear when your program does something that Python doesn’t like. Either Python doesn’t understand what you’re asking, or you’re asking it to do something impossible. 

Whichever it is, the consequence is the same: the program stops. But you can prevent this from happening if you know how to manage exceptions.

To manage an exception in Python, use the instructions  try  and   except  like this:

try:
    numerator = input("State the numerator")
    denominator = input("State the denominator")
    print(numerator/denominator)
except:
    print(“There’s a problem with this operation”)

What’s going on here? The instruction that may generate an error is in the  try  . If it doesn’t generate one, the program continues, and everything runs smoothly. 

However, if it generates an exception, the instruction in  except  will be executed, regardless of the type. This is because you haven’t specified a type after the   except  keyword. Therefore, you receive a vague message that doesn’t tell you the cause of the error. 

But what exceptions might occur in your operation? I can think of at least three:

  • ValueError: The user has entered something other than figures and decimal points  .  (i.e.,   a  ,  $  , or  10,5  ,etc.).

  • ZeroDivisionError: An error caused by a division by 0, which is mathematically impossible.

  • TypeError: The user tried to carry out an operation between a number and a string.

Here’s how to manage these cases:

try :
    numerator = input("State the numerator")
    denominator = input("State the denominator")
    print(int(numerator)/int(denominator)) 
except (ZeroDivisionError, ValueError):
    print("There’s a problem with the code")

As you can see, this time we caught the exceptions  ZeroDivisionError  and  ValueError  by providing an error message. We could have given a bit more detail, though! Let’s do that now:

try :
    numerator = input("State the numerator")
    denominator = input("State the denominator")
    print(int(numerator)/int(denominator)) 
except ValueError:
    print("ValueError: You must have written something other than numbers with or without a decimal point")
except ZeroDivisionError:
    print("ZeroDivisionError: It looks like you’re trying to divide by zero—are you sure about that?")
except :
    print("I’m not sure what’s happened—I can’t help, sorry!")
finally:
    print("The instruction 'try except' was successfully executed!")

That’s better! There is now a message for each type of error. The last  except  branch is displayed for all errors other than  ValueError  and  ZeroDivisionError  . The  finally  branch runs at the end of the exception block, regardless of the type raised. It’s a concluding remark that always appears, whether things have gone smoothly or not!

But we can go one better! For the moment, we caught the exception but haven’t managed it. So let’s see how to do this now so the program can continue. 

try :
    numerator = input("State the numerator")
    denominator = input("State the denominator")
    print(int(numerator)/int(denominator)) 
except ValueError:
    print("ValueError: You must have written something other than numbers with or without a decimal point\n
    Try again!")
    while True:
        numerator = input("State the numerator. Please use only numbers and decimal points.")
        denominator = input("State the denominator. Please use only numbers and decimal points.")
        if (numerator.isdigit() and denominator.isdigit() and int(denominator) != 0):
            break
    print(int(numerator)/int(denominator)) 
except ZeroDivisionError:
    print("ZeroDivisionError: It looks like you’re trying to divide by zero—are you sure about that?")
except :
    print("I’m not sure what’s happened—I can’t help, sorry!")
finally:
    print("The instruction 'try except' was successfully executed!")

Not only does the code above catch the exception  ValueError  , but it fixes it to allow the program to continue. 

For example, if your numerator or denominator contains something other than figures, a  ValueError  is raised. You then enter an infinite loop that asks you to enter a new numerator and denominator. The loop will continue as long as these contain anything other than numbers. So let’s check that the denominator isn’t 0. And there you have it—the exception is caught and managed!

One last thing—you can also raise exceptions manually, which is handy if you want to apply a specific rule to your program to prevent something from happening. 

For example, imagine you’re creating a program to check users’ passwords for entering a program. You could write this:

password = input("What’s the password?")
if password != "1234":
    raise Exception("Intruder detected!")
else:
    print("Welcome to the club!")

We raised an exception manually by using the keyword  raise  . 

We could also have chosen one of the built-in exceptions in Python, like this:

password = input("What’s the password?")
if password != "1234":
    raise TypeError("The password should be a set of numbers. Intruder detected!")
else:
    print("Welcome to the club!")

Manage Exceptions in Software and Web Projects

In the following screencast, you’ll see how to manage exceptions in our rock-paper-scissors project. I’ll do this for the software and web versions, starting with the tkinter project

In this screencast, I caught the different exceptions generated by our program. To do this, place all the lines that may generate errors in  try  and  except  blocks. These errors were  RuntimeError  ,   NameError  and_tkinter.TclError   .

The exception  _tkinter.TclError  is a special case. It doesn’t belong to the standard Python library and can’t be used after the instruction  except  unless imported from the  tkinter  module. Another solution would be to not write anything after  except  , which would catch all exceptions generated in the  try  .

Now let’s move on to the web version with Flask!

In this screencast, you saw how to use the function  abort  to link a specific route to an exception. You also saw how to link the decorator@app.errorhandler()to a function to redirect a page generating an HTTP error to a specific template. 

Finally, let’s move on to the Django version. 

As you saw in the screencast, managing HTTP errors with Django is simple. All you have to do is create an HTML file with the target HTTP code as its name. This way, the user will be redirected to the HTML file template whenever an HTTP error with that specific code is generated. 

Over to You!

Let’s finish with an exercise. The code below outputs a message to show a person’s age. Your task is to catch all possible exceptions and manage them, so the program continues running.

Here’s the code for the exercise:

from datetime import *

year_of_birth = int(input("What is your year of birth?"))
age = int(datetime.now().strftime("%Y")) - year_of_birth
print(f"You are {age} years old.")

Have a go, and then compare your work with mine in the GitHub repository

Let’s Recap!

  • You can manage exceptions in a  try  and  except  block.

  • The  try  block contains the instruction that may raise an exception.

  • The  except  block contains instructions if the exception is raised.

  • You can provide the name of an exception (or an exception group) after the instruction  except  . If nothing is stated after  except  , it means it will apply to any exception raised. 

  • The instruction  finally  comes at the end of a  try  and  except  block, no matter the result.

Now you know how to manage exceptions; it’s high time to exterminate some bugs, don’t you think? If you agree, come with me to the next chapter!

Example of certificate of achievement
Example of certificate of achievement