Concepts / Reading Python Tracebacks

Reading Python Tracebacks

An AssertionError is raised when an assert statement's condition is False, and it appears in the traceback with the file name and line number where the assertion failed.

  • Programming

The Failure Path

When an assert statement evaluates a condition as False, Python raises an AssertionError immediately. The current function stops at that point, and the exception moves up through the call stack unless an exception handler catches it. A traceback records this path so you can investigate both the function that failed and the calls that led to it.

What do you think happens?

A decorated function reaches a false assertion on its first attempt, and the decorator is configured to retry failures. What happens next?

  • The assertion is ignored and the function continues
  • The decorator catches the exception, logs the failed attempt, and re-executes the function
  • Only the failed assertion line is executed again
  • The caller always receives the exception immediately
Reveal answer

Answer: The decorator catches the exception, logs the failed attempt, and re-executes the function.

A retry decorator intercepts the wrapped function's execution. It can catch AssertionError, record the attempt, and execute the entire wrapped function again, up to its maximum number of attempts.

Decorator Interception

A decorator places a wrapper between the caller and the original function. The caller starts the wrapped operation, the wrapper invokes the original function, and the original function either completes or raises an exception. If an exception occurs, the wrapper's exception handler can catch it before it reaches the caller. A retry decorator then decides whether to log the failure, retry the operation, or propagate the exception.

callsinvokesraisescaught byevaluatesretryfinish or propagateCallerRetry wrapperexception handlerWrapped functionassert statementAssertionErrorRetry decisionCaller receivesresult or error
What happens to control flow when a decorated function is called, its assertion fails, and the decorator handles the exception?

Retrying the Whole Operation

A retry mechanism does not jump back to only the assertion line. It re-executes the entire wrapped function. The decorator catches the exception, logs the failure with the attempt number, and starts the function again. This process continues until the function succeeds or the maximum number of attempts is reached.

raisescaught and recordedcontinue evaluationretrystop retryingcomplete or fail againAttempt 1function executesAssertionErrorassertion is falseFailure logattempt numberRetry decisionmaximum not reachedAttempt 2entire function re-executesFinal outcomesuccess or last exception
After an AssertionError, how does the retry mechanism catch it, decide whether to retry, and re-execute the function?

First Attempt Fails, Second Attempt Proceeds

Trace a decorated function that fails with an exception on its first attempt and is then re-executed by a retry decorator.

Call enters the wrapper: The caller invokes the decorated function, so execution first passes through the decorator's wrapper.

Original function runs: The wrapper invokes the original function. The function performs its work and reaches an assertion.

Assertion fails: Because the assertion condition is False, Python raises an AssertionError and stops the current function.

Wrapper catches the exception: The retry decorator catches the exception, logs the failure with the attempt number, and checks whether another attempt is allowed.

Function runs again: The decorator re-executes the entire wrapped function rather than resuming at the failed assertion line.

Process ends: If a later attempt succeeds, execution continues. If attempts continue to fail until the limit is reached, the decorator may raise the last exception or return a default value, depending on its design.

The wrapper controls the transition from failure to retry. The original function is started again from the beginning of its wrapped execution.

Reading the Call Stack

callsinvokesraisesCaller framestarted the callDecorator frameintercepted executionFunction framecontains assertionAssertionErrororiginates here
Which function calls led to the failure, and how do the traceback frames connect the decorated wrapper to the original function?

Read traceback frames as a path through the program. Earlier frames show calls that led to the failure. A decorator frame explains why the wrapper was involved, but the deepest frame, listed last, identifies where the exception originated. For an AssertionError, inspect that final relevant frame for the file name, line number, function, and assertion that evaluated to False.

narrows towithincontainsraisesFile namesource fileLine numberlocationFunctionexecution contextassert statementcondition was FalseAssertionErrorfailure
How do the traceback's file name and line number identify the exact assert statement whose condition evaluated to False?
  1. Start with the final traceback frame rather than the decorator frame.
  2. Read the file name to identify the source file.
  3. Read the line number to locate the relevant source line.
  4. Confirm that the line contains the assertion whose condition evaluated to False.
  5. Read earlier frames to understand which caller and wrapper led to the failure.
  6. Check retry logs to determine whether the decorator caught the exception and started another attempt.

Mistakes in Traceback Reading

  • Treating the decorator frame as the failure location

    The wrapper is part of the call stack and may catch the exception, but the deepest frame listed last shows where the exception actually originated.

    Fix: Inspect the final relevant frame and use its file name and line number to locate the failed assertion.

  • Assuming a retry resumes at the failed line

    A retry decorator re-executes the entire wrapped function.

    Fix: Trace the next attempt from the beginning of the wrapped function and account for repeated side effects.

  • Assuming every caught failure reaches the caller immediately

    The decorator can catch the exception, log the attempt, and retry before deciding what the caller receives.

    Fix: Look for the decorator's retry decision and maximum-attempt behavior.

  • Ignoring the line number

    The traceback supplies a file name and line number that pinpoint the failed assertion.

    Fix: Open the named source file at the reported line and inspect the assertion condition.

Read the traceback in two passes. First, locate the origin of the exception by finding the deepest frame and its source location. Second, reconstruct the route to that frame by reading the earlier caller and decorator frames. This separates the question “Where did it fail?” from the question “Why was this function running?”

Traceback Practice

MEDIUM

A traceback lists a caller frame, a decorator frame, and a final frame inside the original function. The final frame identifies a source file and line containing an assert statement. The decorator log says the first attempt failed and another attempt began. Explain where the AssertionError originated, what the decorator did, and what code must be considered when checking for repeated side effects.

Hints
  • Use the deepest frame to identify the origin.
  • Separate catching the exception from creating the exception.
  • A retry starts the entire wrapped function again.

Practice Solution

Interpret the traceback and retry information from the practice situation.

Locate the origin: The AssertionError originated in the deepest frame, inside the original function at the reported file and line number.

Interpret the decorator frame: The decorator frame shows that a wrapper intercepted the call and handled the exception; it is not necessarily where the assertion failed.

Interpret the retry log: The first attempt failed, the decorator logged that attempt, and the retry mechanism started another execution.

Check repeated work: Because the whole wrapped function runs again, any side effects performed before the assertion can occur again on the retry.

The traceback identifies the failed assertion, while the decorator frames and logs explain how the failure was handled and why another full execution occurred.

Key Takeaways

  1. An AssertionError is raised immediately when an assert condition is False.
  2. The deepest traceback frame, listed last, identifies where the exception originated; decorator frames show the surrounding call path.
  3. A retry decorator can catch the exception, log the attempt, and re-execute the entire wrapped function up to a maximum number of attempts.
  4. Use the traceback's file name and line number to locate the failed assertion in source code.
  5. Because retries repeat the whole function, side effects can happen again on each attempt.

Key Takeaways

  • Find the deepest traceback frame to locate the actual AssertionError origin.
  • Use the file name and line number to inspect the assertion whose condition evaluated to False.
  • Remember that a decorator can catch the exception before it reaches the caller.
  • A retry re-executes the complete wrapped function, not only the failed line.
  • Inspect repeated side effects and retry logs when diagnosing decorated failures.