Part 3: Variables, Watch, and Data Inspection

Introduction

You've set breakpoints and paused executionβ€”now what? The real power of debugging comes from inspecting your application's state: variables, objects, data structures, and call stacks.

I once spent 2 hours debugging why an API returned incorrect data. The problem? A nested dictionary three levels deep had the wrong structure. The Variables panel showed me the entire object tree in 30 seconds. This article teaches you how to inspect, evaluate, and understand data during debugging.

The Variables Panel

When execution pauses, the Variables panel shows all variables in the current scope.

Understanding Scope Sections

def calculate_order_total(order_id, user_id):
    # Breakpoint on next line
    order = get_order(order_id)
    user = get_user(user_id)
    
    subtotal = sum(item['price'] * item['qty'] for item in order['items'])
    discount = get_user_discount(user)
    total = subtotal - discount
    
    return total

Variables panel shows:

  • Locals: Variables in the current function

  • Globals: Module-level variables and imports

Inspecting Complex Objects

Click the triangle to expand objects:

Real scenario: I was debugging why shipping calculations were wrong. Expanded the order object and found:

Modifying Variables During Debugging

You can change variable values while debugging!

Right-click variable β†’ "Set Value"

At breakpoint:

  1. See discount_percent: 150 in Variables panel

  2. Right-click discount_percent β†’ "Set Value"

  3. Enter 15

  4. Continue debugging to test if fix works

Perfect for: Testing fixes without restarting the entire debug session.

Filtering Variables

With many variables, use the filter box (βŒ₯⌘F while focused on Variables):

The Watch Panel

Monitor specific expressions that update as you step through code.

Adding Watch Expressions

Watch expressions:

Watch expressions update as you step through code. Perfect for tracking calculations!

Real Example: Debugging a Pricing Bug

As I stepped through, watch panel showed:

Saw immediately that annual discount overwrote the user's discount instead of stacking.

Advanced Watch Expressions

Watch panel accepts any Python expression:

Copying Values from Watch

Right-click watch expression:

  • Copy Value: Copy the result value

  • Copy as Expression: Copy the expression itself

Useful for:

  • Pasting values into code

  • Sharing debugging info

  • Testing expressions in debug console

Call Stack Inspection

The call stack shows the sequence of function calls that led to the current line.

Understanding the Call Stack

Call stack shows:

Click any frame in the call stack to see:

  • Variables in that frame's scope

  • Source code at that point

  • State when that function was called

Real scenario: Exception in check_inventory(). Call stack showed:

Clicked process_order frame and saw user_id=456, which helped me understand the context of the error.

Call Stack for Async Code

Python async code shows in call stack differently:

Call stack:

Shows async call hierarchy clearly.

Debug Console REPL

The debug console isn't just for viewingβ€”it's a full Python REPL running in your code's context.

Exploring Object Structure

Debug console:

All without modifying your code!

Testing Code Fixes

Debug console - test fix:

Now update the code with confidence.

Running Complex Queries

Debug console:

Explore data interactively!

Importing Modules in Debug Console

Debug console:

Full Python environment at your fingertips!

Real-World Example: Debugging a Data Pipeline

I built a data processing pipeline that transformed customer records. Output had inconsistent data.

The Code

Problem: Some customers had wrong segments and missing data.

Debugging Session

Set Conditional Breakpoint

Only pause on customers with issues:

Breakpoint on line 9 (for loop) Condition: record.get('customer_id') == 'CUST-12345'

Inspect Record Structure

Use Watch Panel

Added watch expressions:

Watch panel showed the error immediatelyβ€”total: None caused TypeError in sum().

Test Fix in Debug Console

Verify Full Flow

Step through with F10:

Found second bugβ€”LTV of 225 should put customer in 'new' segment, but threshold might be wrong.

Check Segment Logic

Complete Fix

Total debugging time: 5 minutes using Variables panel, Watch, and Debug Console.

Without debugger: Adding print statements, processing thousands of records, analyzing output logsβ€”easily 30+ minutes.

Advanced Data Inspection Techniques

Inspecting Large Collections

Debug console:

Inspecting Class Instances

Variables panel shows:

Debug console:

Working with JSON Data

Debug console:

Checking Types and Truthiness

Debug console:

Best Practices

1. Use Watch for Calculated Values

Instead of adding print statements for calculations, use watch expressions:

2. Navigate Call Stack for Context

When you hit a breakpoint deep in code, click up the call stack to see:

  • What arguments were passed

  • Where the function was called from

  • Parent function's state

3. Test in Debug Console, Then Update Code

Always test your fix in debug console before modifying code:

4. Copy Expression for Documentation

When you figure out a complex expression in debug console, copy it for code comments or documentation:

5. Use Variables Filter for Large Scopes

When debugging functions with many variables, filter the Variables panel instead of scrolling.

Common Patterns

Pattern 1: Inspect Before Exception

Inspect data to see what causes the exception.

Pattern 2: Watch Accumulator Variables

See total update with each iteration.

Pattern 3: Verify API Responses

Debug console:

What's Next

You now master:

  • Variables panel for inspecting all scopes

  • Watch expressions for monitoring calculations

  • Call stack navigation for understanding context

  • Debug console REPL for testing and exploration

In Part 4: Advanced Debugging Techniques, you'll learn debugging async/await code, exception handling strategies, debugging multi-threaded applications, and using logpoints effectively.


Based on inspecting thousands of variables and debugging complex data pipelines in production Python applications.

Last updated