← Python lessons

Python Input Validation Loop: Ask Again Until Valid

Part of a free Python course — sign up to save your progress and get AI hints.Sign up free

An input validation loop keeps asking with input() until the answer passes your checks, so the rest of the program only sees valid data.

Read Data Validation first. This lesson also uses While Loops and Parameters & Return.

Put the checks in one function

A function that returns the converted value, or None when the text is invalid, keeps the checks in one place.

def parse_age(text):
    if not text.isdigit():
        return None
    age = int(text)
    if age > 120:
        return None
    return age

for text in ["12", "twelve", "121", "0"]:
    print(text, "->", parse_age(text))

This prints 12, None, None and 0. None means "no valid value".

Ask again until the answer is valid

Loop while there is no valid value yet.

def parse_age(text):
    if not text.isdigit():
        return None
    age = int(text)
    if age > 120:
        return None
    return age

age = None
while age is None:
    answer = input("Age (0 to 120): ")
    age = parse_age(answer)
    if age is None:
        print("Enter a whole number from 0 to 120.")
print("Accepted age:", age)

Try twelve, then -1, then 12. The first two answers print the message and ask again. The loop stops after 12.

Test for None, not for False

0 is a valid age, but not 0 is True. A loop on while not age: would reject it.

age = 0
print(not age)
print(age is None)

This prints True, then False. Use is None whenever 0 or "" can be a valid result.

Ask again until the answer is allowed

The same loop works for text answers. .strip() and .lower() clean the answer, then in checks it against the allowed list.

answer = ""
while answer not in ["yes", "no"]:
    answer = input("Play again? (yes/no) ").strip().lower()
print("You chose", answer)

Try maybe, then YES. maybe is not in the list, so the question repeats. YES becomes yes and is accepted. Check a list, not a string: "ye" in "yesno" is True.

Skip invalid records in a list

Data from a list or file has nobody to ask again. Report and skip the bad records instead. The rule stays the same.

def parse_age(text):
    if not text.isdigit():
        return None
    age = int(text)
    if age > 120:
        return None
    return age

rows = ["14", "abc", "200", "9"]
ages = []
for row in rows:
    age = parse_age(row)
    if age is None:
        print("Skipping", row)
    else:
        ages.append(age)
print(ages)

This skips abc and 200, then prints [14, 9].

Note: a real program might also limit the number of retries, or stop when the user types nothing. These examples leave that out.

See also: While Loops, try and except.

Your turn

Complete parse_percentage(text): return the number when text is digits from 0 to 100, otherwise None. Then keep only the valid answers.

def parse_percentage(text):
    # check the digits, convert, check the range, return a number or None
    return None

answers = ["0", "100", "-1", "101", "half", "50"]
valid = []
for answer in answers:
    # append the parsed value when it is not None
    pass
print(valid)

Expected output

[0, 100, 50]