Debugging Techniques in Python
The assert statement verifies that a condition is true; if false, it raises an AssertionError
A Checkpoint for Assumptions
Debugging often means checking whether the program state matches what you believe should be true. Python's assert statement creates a checkpoint for that belief. It verifies a condition: when the condition is true, execution continues silently; when the condition is false, Python immediately raises an AssertionError. This makes the point where an assumption breaks down easier to identify.
An assertion is a development and debugging check for an expected condition. It is not a replacement for handling expected runtime errors.
The Two Execution Paths
Python first evaluates the condition in the assert statement. A true condition produces no output and no error from the assertion, so Python moves to the next line. A false condition causes Python to raise an AssertionError immediately. The program halts at that point unless the surrounding program handles the failure in some way.
What do you think happens?
Suppose a list contains one element and the program checks that its length is at least 1. What happens when Python evaluates the assertion?
Reveal answer
Answer: The assertion passes silently and execution continues.
The condition is true because the list has at least one element. Assertions do not print a success message when their condition is true.
Assert Statement Structure
An assert statement has the keyword assert followed by a condition. The condition can be any boolean expression. Optionally, a comma and a message string can follow the condition. That message is displayed when the assertion fails.
The first form checks only the condition. The second form adds information for the failure case. A descriptive message should explain the assumption being checked or the state that was unexpected.
Checking a Nonempty List
Verify Before Proceeding
A program expects a list to contain at least one element before it proceeds.
Create the expected state: The example creates a list containing one element.
State the assumption: The assertion checks that the list length is at least 1.
Evaluate the condition: Because the list has one element, the condition is true.
Continue execution: The assertion passes without output or an error, and the program continues to the next line.
The assertion confirms the assumption that the list is nonempty.
Ready to continueThe assertion itself produces no success output. The visible output comes from the later print statement, which runs because the condition is true. This distinction matters when tracing execution: a passing assertion allows later statements to run, while a failed assertion prevents later statements from being reached.
When the Assumption Breaks
AssertionErrorWith an empty list, the length condition is false. Python raises an AssertionError at the assert statement, so the later print statement is not reached. The traceback identifies the line that caused the failure, pinpointing where the assumption about the list was violated.
Reading the Failure Location
To locate an assertion failure, connect three pieces of information: the program state immediately before the assertion, the assertion line in the source code, and the traceback produced by the failure. The failed line shows where Python detected that the condition was false. The execution sequence also tells you that statements after that line were not reached.
The custom message makes this failure more informative. Instead of seeing only AssertionError, the developer also sees which assumption mattered: records was expected to contain at least one item. The message does not change the condition; it explains the reason for checking it.
Safe Uses During Development
Use assertions to verify assumptions about program state while developing and debugging. For example, an assertion can check an assumption that a list should already contain at least one element before later code proceeds. A failed assertion then exposes the point where the expected state was not true.
Include a descriptive custom message when the reason for the check may not be obvious. The message should help another developer understand what assumption was violated and why the assertion mattered.
Mistakes to Avoid
Treating a passing assertion as something that prints confirmation
A true assertion passes silently. It does not display a success message.
Fix:
Trace the next line of execution instead. If the assertion is true, later statements can run.Ignoring the AssertionError location
The traceback identifies the line where the assumption was violated.
Fix:
Use the reported assertion line and the program state immediately before it to find the broken assumption.Using an assertion for an expected runtime error
Assertions are a development and debugging tool, and they can be disabled with Python's -O flag.
Fix:
Use proper exception handling for expected runtime errors and do not rely on assertions for production-critical logic.Leaving a failure message too vague
The message does not explain which assumption failed or why the check mattered.
Fix:
Use a descriptive message such as "records must contain at least one item".
Practice the Trace
Consider this program: values = [] followed by assert len(values) >= 1, "values must not be empty" and then print("continue"). Identify the condition's value, the exception raised, the message supplied to the failure, and whether the print statement runs.
Hints
- An empty list has a length of zero.
- Compare zero with the asserted minimum of one.
- A false assertion raises AssertionError immediately.
- Execution stops at the failed assertion, so inspect whether the later line can be reached.
Practice Answer
Trace the empty-list example with the custom message.
Evaluate the condition: The list length is zero, so the condition len(values) >= 1 is false.
Raise the exception: Python raises an AssertionError at the assert statement.
Read the message: The failure includes the custom message values must not be empty.
Check the next line: Execution stops at the failed assertion, so the print statement does not run.
The assertion identifies the exact point where the nonempty-list assumption failed.
Key Takeaways
- assert verifies that a condition is true.
- A true assertion passes silently and execution continues.
- A false assertion immediately raises an AssertionError and stops execution at that point.
- A comma followed by a message string makes a failed assertion more informative.
- Assertions are debugging tools and should not be used for production-critical logic because Python can disable them with the -O flag.
Key Takeaways
- Use assert to verify assumptions about program state during development and debugging.
- A true condition allows execution to continue without assertion output.
- A false condition raises AssertionError at the assertion line and stops execution there.
- Add a descriptive message after a comma to explain the failed assumption.
- Do not rely on assertions for expected runtime errors or production-critical logic.