Lesson 3: Validation & Errors — Data Safety, Type Checking
Learn how to validate command-line arguments in Python using argparse—type checking, required flags, choices, and custom validators with real examples.
Goal: Make sure your CLI tool only accepts valid, well-typed input — and throws helpful errors when users do dumb things.
Why Validation Matters
Your CLI tool is only as good as the inputs it accepts. If someone passes "banana" when you’re expecting a number, things break fast.
Validation protects your logic from crashing, keeps output clean, and makes your script behave like a real tool, not a fragile toy. It’s the armor between your code and the chaos.
What You’ll Learn
- Type enforcement (type=int, type=float, etc.)
- Limiting input with choices=
- Writing custom validators (ranges, positive-only, patterns)
- Validating ranges and simple patterns
- Defensive coding with try/except (optional but useful)
- Using required=True to force input
- Setting up mutually exclusive flags
- Getting clean, automatic error messages (argparse does the heavy lifting)
Core Concepts
1) type=: Convert + Validate in One Shot
type= converts the input and validates at the same time.
parser.add_argument("--age", type=int)
If someone runs:
python app.py --age banana
They’ll get:
error: argument --age: invalid int value: 'banana'
Boom. Safety net.
2) Custom Validation Functions
When built-in types aren’t enough, write your own validator. Great for ranges, positive-only values, “must be a file”, regex checks, etc.
import argparse
def positive_number(value):
ivalue = int(value)
if ivalue <= 0:
raise argparse.ArgumentTypeError("Must be a positive number.")
return ivalue
parser = argparse.ArgumentParser(description="Validate positive numbers")
parser.add_argument("--level", type=positive_number)
args = parser.parse_args()
print(args.level)Try:
python app.py --level -5
…and it gets smacked down.
3) choices=: Only Allow Certain Values
Perfect for “modes”, “environments”, categories, enums, etc.
parser.add_argument("--color", choices=["red", "green", "blue"])
If they try something else, argparse rejects it automatically.
4) required=True: Force a Value
Want to require a flag?
parser.add_argument("--username", required=True)
No --username? argparse yells at them. With love.
5) Mutually Exclusive Flags
If only one option is allowed (like --verbose or --quiet), use a mutually exclusive group:
group = parser.add_mutually_exclusive_group()
group.add_argument("--verbose", action="store_true")
group.add_argument("--quiet", action="store_true")
Passing both becomes an immediate ❌ error.
Sample Code: Clean Input or No Input
import argparse
parser = argparse.ArgumentParser(description="Process numeric input safely")
# Type enforcement
parser.add_argument("--age", type=int, help="Your age in years")
parser.add_argument("--rate", type=float, help="Conversion rate")
# Limited input choices
parser.add_argument(
"--mode",
choices=["easy", "medium", "hard"],
default="easy",
help="Choose difficulty level (easy, medium, hard)"
)
args = parser.parse_args()
print(f"Age: {args.age}")
print(f"Rate: {args.rate}")
print(f"Mode: {args.mode}")
Try it out
$ python3 validate.py --age 30 --rate 1.25 --mode medium
Age: 30
Rate: 1.25
Mode: medium
Bad inputs:
$ python3 validate.py --age banana
# error: argument --age: invalid int value: 'banana'
$ python3 validate.py --mode nightmare
# error: argument --mode: invalid choice: 'nightmare' (choose from 'easy', 'medium', 'hard')
Beautiful. Clean. Practically idiot-proof.
Pro Tips
- Use type= for basic conversion + safety.
- Use custom validators for logic (range checks, positive-only, etc.).
- Use choices= for fixed modes/options.
- Use required=True when missing input should be a hard failure.
- Test invalid inputs on purpose. Your future self will thank you.
- Don’t assume users will follow instructions — enforce rules instead.
Real-World Use Cases
- Fixed modes: --env dev / --env prod
- User inputs like age, tax rate, discount amount (always type-check)
- Sensitive automation flags like --risk, --region, --priority
Bonus: Price Calculator with Validation
import argparse
def positive_float(val):
f = float(val)
if f <= 0:
raise argparse.ArgumentTypeError("Value must be greater than zero.")
return f
parser = argparse.ArgumentParser(description="Calculate price with tax")
parser.add_argument("--price", type=positive_float, required=True)
parser.add_argument("--tax", type=positive_float, default=0.2)
args = parser.parse_args()
total = args.price * (1 + args.tax)
print(f"Total: ${total:.2f}")Coming Up Next
Part 4: Grouping & Subcommands — we’ll organize commands like a pro, split logic into subtools, and make your CLI feel like a real app.
🔁 New here? Catch up from Lesson 1:
Lesson 1: Getting Started with argparse
Got questions or want to share your CLI builds? Drop a comment.
Note
If you find any part of this post unclear or technically inaccurate, I would appreciate hearing from you. Improving the precision of these explanations is an ongoing process, and your feedback helps strengthen the material.