Writing Defensive Code with Input Validation
The Python interpreter recovers from errors and returns a prompt; a script terminates immediately with a traceback.
One Error, Two Outcomes
An invalid value can produce two very different experiences depending on where Python is running. In the interactive interpreter, an error message is followed by a new prompt, so you can enter another command. In a script, the same kind of error causes the program to stop, and Python displays a traceback. This difference is the reason defensive programs must account for invalid input instead of assuming every value will be acceptable.
Following the Failure
A Fahrenheit Conversion Fails
A script reads a Fahrenheit temperature, converts the input to a floating-point number, calculates Celsius, and prints the result. What happens when the input is the string 'fred'?
Read the input: The script receives the string 'fred' as the input value.
Attempt conversion: The statement fahr = float(inp) asks Python to convert the string to a floating-point number.
Raise the exception: The string 'fred' does not represent a valid floating-point number, so Python raises a ValueError.
Stop execution: The calculation and print statements that follow the conversion do not execute.
Read the traceback: The traceback identifies line 2 in fahren.py, displays the statement that failed, and reports that 'fred' could not be converted to a float.
The script terminates immediately with a traceback before it calculates or prints the Celsius result.
The important control-flow fact is that the traceback is not merely a warning printed alongside a continuing program. In this situation, the traceback accompanies termination. Once the conversion raises the ValueError, Python does not continue to the later calculation or output statements in the script.
Understanding ValueError
A ValueError occurs when a function receives an argument of the correct type but an inappropriate value. During conversion, a string is an acceptable kind of argument for int() or float(), but the characters inside that string may not represent a valid number. For example, int('hello') raises a ValueError because the value cannot be interpreted as an integer. Likewise, attempting to convert a string containing letters, such as 'fred', to a floating-point number raises a ValueError.
Reading a Traceback
A traceback is a detailed report of the failure. It shows the sequence of function calls that led to the exception and narrows that sequence down to the line where the error occurred. In the fahren.py example, the message begins with 'Traceback (most recent call last)'. The entry 'File "fahren.py", line 2, in <module>' identifies the file, line number, and top-level script context. Python then displays the statement fahr = float(inp), followed by the exception type and explanation: ValueError: could not convert string to float: 'fred'.
| Traceback detail | What it tells you |
|---|---|
| Traceback (most recent call last) | The following information describes the call chain leading to the error. |
| File "fahren.py", line 2 | The failure occurred in fahren.py on line 2. |
| in <module> | The failing statement was at the top level of the script. |
| fahr = float(inp) | This is the statement where the failure occurred. |
| ValueError | The exception is a value-related conversion error. |
| could not convert string to float: 'fred' | The supplied value does not have a valid floating-point format. |
Reading the source example's traceback from general context to specific cause.
When a script fails, read the traceback from its context toward its final error message. First locate the file and line, then inspect the displayed statement, and finally use the exception type and message to understand why that statement failed.
Recovering at the Prompt
The interactive interpreter provides a forgiving environment for experimentation. If a conversion raises a ValueError there, Python displays the error message and returns to a new prompt. You can then try another command or provide a different value. This recovery applies to the interpreter session; it does not mean that the same unhandled error will allow a script to continue.
| Interactive interpreter | Python script |
|---|---|
| Shows an error message | Shows a traceback |
| Returns to a new prompt | Terminates immediately |
| Allows another command to be entered | Does not execute later statements |
Designing for Invalid Input
Defensive programming begins with recognizing that input can be invalid. A program that reads a temperature cannot assume that every input represents a number. If it sends an invalid value directly into float(), the script may terminate before performing its calculation. Input validation is therefore the step of treating incoming data as something that must be checked or handled before the rest of the program depends on it.
Mistakes to Avoid
Assuming that an error in the interpreter means the program will continue when run as a script.
A script does not return to an interactive prompt after an unhandled exception. It terminates with a traceback.
Fix:
Test how the complete script responds to invalid input and plan explicit error handling.Treating every conversion failure as a type mismatch.
The argument is a string, but its value does not represent a valid floating-point number. This is a ValueError.
Fix:
Distinguish the type of an argument from whether its value is appropriate for the requested conversion.Reading only the final exception name and ignoring the traceback location.
The traceback provides the path to the failing statement and helps locate the source of the error.
Fix:
Read the file and line information, inspect the displayed statement, and then interpret the exception message.Expecting statements after a failed conversion to run.
The script stops immediately when the exception occurs, so later statements are not executed.
Fix:
Treat the failing statement as the point where normal control flow ends unless the exception is handled.
Practice the Diagnosis
A script receives the string 'hello' and attempts to convert it to an integer. Explain which exception you expect, whether the script continues to its next statement, and which parts of the traceback you would inspect first.
Hints
- Ask whether the value represents a valid integer.
- Separate the behavior of the interactive interpreter from the behavior of a script.
- Look for the file name, line number, failing statement, exception type, and explanatory message.
What do you think happens?
A script attempts a numeric conversion, the conversion raises a ValueError, and the next statement prints a message. Does the print statement execute?
Reveal answer
Answer: No, because the script terminates at the unhandled exception.
An unhandled ValueError in a script stops execution immediately. Python prints a traceback, and later statements do not execute.
Key Takeaways
- The interactive interpreter reports an error and returns to a prompt, while a script with an unhandled exception terminates.
- A ValueError occurs when a function receives an argument whose value is inappropriate, including a string that cannot be converted to the requested numeric type.
- A traceback identifies the call sequence, file, line, failing statement, exception type, and explanatory message.
- Statements after an unhandled exception in a script do not execute.
- Understanding termination motivates input validation and exception handling with try and except blocks.
Key Takeaways
- The interpreter recovers to a new prompt after an error, but a script terminates with a traceback.
- ValueError describes an inappropriate value, such as a non-numeric string passed to int() or float().
- A traceback is a roadmap from the call sequence to the exact failing line and exception message.
- Input validation and exception handling are necessary because real program input cannot be assumed to be valid.