Data Validation
Data validation checks whether data meets the rules for its intended use. Data can come from a person, a file, a list or another program. Decide the rules first, convert types where needed, and reject or correct invalid data before using it.
For an age field, suppose the rule is a whole number from 0 to 120,
inclusive. Successfully turning text into a number is only one check:
-5 is a number but is not a valid age under this rule.
Convert text and numbers
input() returns text, even when someone types digits.
int("12")converts whole-number text to an integer.float("12.5")converts decimal text to a floating-point number.str(12)converts a value to text.
age_text = "12"
price_text = "3.50"
age = int(age_text)
price = float(price_text)
label = "Age: " + str(age)
print(age + 1)
print(price * 2)
print(label)
The output is 13, 7.0 and Age: 12. For display with a fixed
number of decimal places, use String Formatting.
int("3.5") and int("twelve") raise ValueError. Converting
int(3.5) instead gives 3: it truncates towards zero. Do not use
int(float(text)) to accept whole-number data, because it can silently
discard a fractional part.
Handle conversion failure, then check the range
This function expects a string. It accepts text that Python's int() can convert to an integer, then checks that the result is from 0 to 120 inclusive. Surrounding whitespace and a leading plus or minus sign are allowed by conversion; the range check rejects negative ages. The function returns the converted age, or None when conversion or the range check fails.
def parse_age(text):
try:
age = int(text)
except ValueError:
return None
if age < 0 or age > 120:
return None
return age
for text in ["12", "twelve", "-1", "121", "3.5", "0", "120"]:
print(text, "->", parse_age(text))
try attempts the conversion. If it raises ValueError, the matching
except block handles that failure instead of letting the program stop.
Catch the specific error you expect. Other programming errors should still
be visible.
The accepted values are 12, 0 and 120. The other examples return None.
Validation does not prove someone's age is true; it only checks these rules.
Ask again when interactive data is invalid
Read While Loops and Parameters & Return before this example.
def parse_age(text):
try:
age = int(text)
except ValueError:
return None
if age < 0 or 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(f"Accepted age: {age}")
Try twelve, then -1, then 12. The first two answers cause a
retry. The loop stops after 12. Use age is None, not not age:
zero is a valid age under this rule.
With file or list data, you might report and skip an invalid record instead of asking a person again. The validation rule can stay the same.
Check presence and allowed values
name = " "
answer = "maybe"
print(name.strip() != "")
print(answer in ["yes", "no"])
Both checks print False. .strip() removes surrounding whitespace,
so the name check rejects blank text. Membership in a list checks a complete
allowed answer. answer in "yesno" would check substrings instead and
could wrongly accept incomplete answers.
Your turn
Complete parse_percentage(text) for a string argument. Convert it with int(), then accept the result only if it is from 0 to 100 inclusive. Return the integer when valid; return None when conversion raises ValueError or the number is outside that range. You do not need a separate digits-only check.
def parse_percentage(text):
# Convert safely, check both boundaries, and return a number or None.
pass
for answer in ["0", "100", "-1", "101", "half", "50.5", ""]:
print(parse_percentage(answer))
Expected output
0
100
None
None
None
None
None
See also: Reading Input, Comparisons and Logical Operators, Debugging.
Practise this in the free Python course, where every exercise checks your code instantly.