Chapter 8, Lesson 3 Text

Lesson Three: Input Validation with "try / except"

 

Right and Wrong keyboard inputThe users that run computer programs may not follow the program instructions. Whenever the program asks for a specific kind of input - such as a number or alphabetic string - the user may actually type in something completely different!

Sometimes these mistakes are accidental, and a user has simply typed too fast or not read or understood the instructions. In other cases, a user might deliberately try to "break" your program by doing something unexpected. Either way, a high-quality program will carefully verify user input to make sure it meets the requirements. If a program tries to process invalid input, it might crash with an exception or produce incorrect results.

Risky Numeric Conversions

All user input is read from the console with input(), which returns a string value. The value may contain an integer like "42" or floating point value like "3.14". if your program needs to convert the string to an integer or float data type, you can use the int() and float() functions on that string data. You are familiar with int() and float() from earlier lessons.

The examples below pass the string result from the input() function directly into the int() or float() functions, which will return an integer or floating point result to the variables.

intAnswer    = int(input("In what year were you born? "))        
floatAnswer  = float(input("How much do you want to spend on a milkshake? "))

This works quite well when the user types in a string that contains a valid integer for int() or a valid decimal value for float(). But what happens when the user gives unexpected input? Try running the sample below and enter a non-integer value like "oops" or "2003.4" for the first question.

Try It Now

intAnswer = int(input("In what year were you born? "))
floatAnswer = float(input("How much do you want to spend on a milkshake? "))
print(intAnswer)
print(floatAnswer)

When int() or float() are given invalid string data to convert, they will throw a ValueError exception when those statements are executed.

In what year were you born? oops
Traceback (most recent call last):
  File "code1.py", line 1, in 
    intAnswer    = int(input("In what year were you born? "))
ValueError: invalid literal for int() with base 10: 'oops'

As you know, exceptions will normally halt your program immediately, and that's something we'd like to avoid!

Catching Exceptions with "try / except"

Fortunately, it is possible to build a safety net in your code! When exceptions happen at run-time, you can "catch" them with protective code that will handle the error gracefully instead of halting the program with an ugly error message.

Whenever you write code that can possibly throw an exception, you can indent that code inside a "try" block. Start with the "try" keyword, following by a colon. Then, underneath, indent the risky code inside the body of the "try" area.

try:
   intAnswer    = int(input("In what year were you born? "))        
   floatAnswer  = float(input("How much do you want to spend on a milkshake? "))

To end the "try" block, use the "except" keyword, again followed by a colon. "except" defines another block of code that will run only if an exception happens from a statement inside the "try" block.

try:
   intAnswer    = int(input("In what year were you born? "))        
   floatAnswer  = float(input("How much do you want to spend on a milkshake? "))
except:
   print("You entered an incorrect value!")

As summarized in the diagram below, the statements inside a "try" block will run normally. If no exception happens (green path), the "except" block will be skipped and the program flow will continue after the indented "except" block. But if an exception happens anywhere inside a "try" block, the program flow (red path) will immediately move to the "except" block, and the remaining statements inside "try" are skipped.

Illustration of exception flow

We've improved our sample code with try / except around the risky parts. Run it, enter some invalid data and observe the results!

Try It Now

try:
intAnswer = int(input("In what year were you born? "))
floatAnswer = float(input("How much do you want to spend on a milkshake? "))
print(intAnswer)
print(floatAnswer)
except:
print("You entered an incorrect value!")

The statement(s) inside the "except" block will only run if some exception happens. Otherwise, the code will continue normally and the "except" statements are skipped. You can verify this by re-running the example and entering correct data that won't cause an exception.

Using "else" or "finally" with "try / catch"

You may want to run some code after the "try / catch" blocks are finished, and you can add optional "else" or "finally" blocks at the end. These statements will mark blocks of code that run either when no exceptions happened ("else") or no matter what happened ("finally").

We've added an "else" and "finally" block at the end of our example. Try running it with both valid and invalid inputs. Can you predict the messages that will be printed in each case?

Try It Now

try:
intAnswer = int(input("In what year were you born? "))
floatAnswer = float(input("How much do you want to spend on a milkshake? "))
print(intAnswer)
print(floatAnswer)
except:
print("You entered an incorrect value!")
else:
print("Thanks for entering correct values.")
finally:
print("We're done here.")

 

Validating Numeric Ranges

When your program asks the user for a numeric value, will any value work, or should the answer be limited to a particular range? Imagine asking the user for his or her age, and getting a valid integer input like 9001. That's an unreasonably large number that may actually cause problems later in your program. The user also might enter a negative value like -50 that doesn't make any sense at all.

You may wish to validate a numeric input to make sure it is between some minimum and maximum value. A human age, for example, might be limited to an integer between 0 and 150. You don't need any special Python keywords or functions to handle this validation. Just write some "if" logic with comparison operators. In the example below, we limit the year to a number between 1900 and 2050 and the cost of a milkshake to a value between $0.50 and $10.00.

Try It Now

try:
intAnswer = int(input("In what year were you born? "))
floatAnswer = float(input("How much do you want to spend on a milkshake? "))
if (intAnswer >= 1900) and (intAnswer <= 2050): # if in valid range 1900 - 2050
print(intAnswer)
else: # else not valid
print("Invalid Age")
if (floatAnswer >= 0.50) and (floatAnswer <= 10.00): # if in valid range 0.50 to 10.00
print(floatAnswer)
else: # else not valid
print("Invalid cost")
except:
print("You entered an incorrect value!")
else:
print("Thanks for entering correct values.")
finally:
print("We're done here.")

The exact nature of the error-handling logic will depend on your program. How should your "if" logic and "try/except" blocks be laid out to correctly validate your particular situation? What needs to be done when invalid input is detected? That's for you to decide!

Looping until Successful

Users will often want a chance to correct any mistakes made when entering data. It can be frustrating if your program simply prints an error message and quits when the first small problem arises! Consider writing loops to continue gathering user input until the correct data is received.

A "while" loop usually makes a good choice for validation. You want to loop "while" the user has not yet entered the correct information. Of course, the exact details are up to you and depend on your program needs. You might also consider a "for" loop that will only give the user a certain number of chances before giving up.

Let's return to our example one last time and add a "while" loop around each of the input values. Notice that we are now using two different "try / except" blocks - one for each of the values. One "while" loop surrounds the first input validation area and another "while" loop covers the second area.

Try It Now

# get and validate first user input
while True: # loop until we break out
try:
intAnswer = int(input("In what year were you born? "))
if (intAnswer >= 1900) and (intAnswer <= 2050): # if in valid range 1900 - 2050
print("Validated: ",intAnswer)
break # get out of while loop!
else: # else not valid
print("Invalid year; must be between 1900 and 2050.")
except:
print("Please enter an integer")
# get and validate second user input
while True: # loop until we break out
try:
floatAnswer = float(input("How much do you want to spend on a milkshake? "))
if (floatAnswer >= 0.50) and (floatAnswer <= 10.00): # if in valid range 0.50 to 10.00
print("Validated: ",floatAnswer)
break # get out of while loop!
else: # else not valid
print("Invalid cost; must be between 0.50 and 10.00")
except:
print("Please enter a decimal value")
 

 

Run the code and watch how the program reacts to a variety of bad input values. The sample run below demonstrates all of the validation logic.

In what year were you born? twenty-ten
Please enter an integer
In what year were you born? 1850
Invalid year; must be between 1900 and 2050.
In what year were you born? 2005
Validated:  2005
How much do you want to spend on a milkshake? nothing
Please enter a decimal value
How much do you want to spend on a milkshake? 0
Invalid cost; must be between 0.50 and 10.00
How much do you want to spend on a milkshake? 5.50
Validated:  5.5

Again, your own programs may require different validation logic! You can make decisions like limiting the number of retries, giving hints or performing different kinds of validations. As a programmer, you should be comfortable testing conditionswriting loops and "if else" logic to get the program behavior you want. The new "try / except" blocks are just another tool in your kit to help validate input values.

As you can see, validating user input can take some effort and quite a few lines of code. Professionally written programs must include this kind of validation logic, because they are used by many people that may or may not follow instructions. We are going to make sure you know how to write validation logic yourself in this chapter. However, later in the course, our examples may skip most of the validation steps to keep the code short and focused on new skills.

 

Work with Me: Verifying a Social Security Number

 

In this program, you are going to ask the user to enter an imaginary social security number. These numbers are assigned to all U.S. citizens and will uniquely identify that person to banks, government offices and other organizations. Your program should verify the input to make sure it is a valid social security number.

A social security number has 9 integer digits and can be written as a number between 000000000 and 999999999. To verify this input, you will want to make the following checks:

  • Ensure the input string has a length of 9
  • Ensure that the input string is a valid integer (use int() for conversion)
  • Limit the number of attempts to 3. If the user enters 3 invalid numbers, print an error message and quit the program. This can be done with a "for" loop that loops 3 times, and breaks out as soon as successful input is received.

We are going to let you create this entire program without any starter code. Programmers will often need to write complete programs, starting with nothing more than general requirements as shown above. You can choose your own variable names and create whatever input and printed output messages seem to fit the situation. See below for some sample output (which you do not need to match).

Practicing writing your own code is important, so challenge yourself! Remember, you can click the "Show Hint" button for a clue or "Show Solution" to see one way to write the code.

Try It Now

  

Console

Here is one example run using the solution code. Remember, your own version may look very different; there are many ways to meet the general program requirements.

Please enter a 9-digit Social Security Number: ninety-nine
A SSN must be 9 digits long
Please enter a 9-digit Social Security Number: abcdefghi
You must enter all integer digits
Please enter a 9-digit Social Security Number: 111111111
Thank you for entering a valid SSN: 111111111
Program complete

Here is a similar run in which the user enters bad data on all three attempts.

Please enter a 9-digit Social Security Number: error on
An SSN must be 9 digits long
Please enter a 9-digit Social Security Number: each
An SSN must be 9 digits long
Please enter a 9-digit Social Security Number: attempt
An SSN must be 9 digits long
Program complete
If you look at the solution code, and you are puzzled by how it works, try copying it to your source panel, adding the "pdb" debugger, and stepping through the program line-by-line to follow the logic. You should know all of the individual concepts and functions like loops, if/else, len(), int(), etc. Putting the skills you know together in creative ways to make a larger program - with minimal guidance - is the fundamental job of most programmers!

Last modified: Sunday, 18 August 2019, 9:48 PM