Skip to main content

PuDB

PuDB is a modern, full-screen console debugger for Python that transforms the debugging experience in terminal environments. It provides a visually rich, interactive interface with syntax highlighting, variable inspection, and advanced breakpoint management—all accessible directly from your terminal.

Unlike the standard PDB, PuDB offers a split-pane layout, real-time variable views, and powerful navigation via keyboard shortcuts. Its support for remote debugging and customizable themes makes it a versatile choice for local development, server-side debugging, and educational use.

PuDB excels in scenarios where:

  • Real-time visualization of code execution is needed
  • Complex data structures require inspection
  • Debugging is performed on remote servers or containers
  • Interactive learning of Python debugging concepts is desired

Basics

Installation

# Basic installation
pip install pudb

# With additional features
pip install pudb[all]

# Verify installation
python -c "import pudb; print('PuDB installed successfully')"

Starting PuDB

Method 1: Insert Breakpoint in Code

import pudb
pudb.set_trace() # Execution will pause here with visual interface

Method 2: Run Script with PuDB

python -m pudb script.py

Method 3: Set as Default Debugger

export PYTHONBREAKPOINT=pudb.set_trace

Then use the standard breakpoint() function:

breakpoint()  # Will use PuDB instead of PDB

Method 4: Command Line with Arguments

# Run with arguments
python -m pudb script.py arg1 arg2

# Start debugging from specific line
python -m pudb --continue script.py

PuDB Interface Components

Main Areas

  1. Source Code Panel - Shows current code with syntax highlighting and line numbers
  2. Variables Panel - Displays local and global variables with expandable structures
  3. Stack Panel - Shows call stack with frame navigation
  4. Breakpoints Panel - Lists all active breakpoints with location information
  5. Command Line - For entering expressions and interactive commands

Interface Layout

┌─────────────────────────────────────────────────────────────┐
│ [Source Code Panel] │ [Variables Panel] │
│ Line numbers, syntax │ Local and global vars │
│ highlighting, current │ Expandable data structures │
│ execution point │ │
├─────────────────────────────────────────────────────────────┤
│ [Stack Panel] │ [Breakpoints Panel] │
│ Call stack frames │ Active breakpoints list │
│ Frame navigation │ Breakpoint management │
├─────────────────────────────────────────────────────────────┤
│ [Command Line / Expression Evaluator] │
└─────────────────────────────────────────────────────────────┘

PuDB Commands 🔖

# Navigation and flow control
n / next # Execute next line (don't step into functions)
s / step # Step into function calls
c / continue # Continue execution until next breakpoint
r / return # Continue until current function returns
f / finish # Continue until current function returns (alias for r)
u / up # Move up one stack frame
d / down # Move down one stack frame
t / top # Go to the top of the call stack
j <line> / jump # Jump to specific line number
until <line> # Continue until line number
unt # Continue until line greater than current

# Breakpoints
b # Toggle breakpoint at current line
B # Focus breakpoints panel / Show breakpoints list
H # Go to current location (jump to current execution line)
m # Module browser (browse and set breakpoints in modules)

# Information and inspection
l / list # Show current code
ll / longlist # Show entire function
w / where # Show stack trace
bt # Show stack trace (alias)
p <expr> # Print expression
pp <expr> # Pretty-print expression
a / args # Show function arguments
whatis <expr> # Show type of expression
source <expr> # Show source code of object
rv / retval # Show return value

# Variable commands
!<statement> # Execute Python statement
interact # Start interactive interpreter
alias <name> <command> # Create command alias
unalias <name> # Remove alias
display <expr> # Auto-display expression
undisplay <expr> # Stop auto-displaying

# Interface controls
V # Toggle variables panel / Focus variables panel
S # Toggle stack panel / Focus stack panel
C # Focus code window
B # Focus breakpoints window
o # Options dialog / Access configuration settings
? # Help (show keyboard shortcuts and help)

# Advanced navigation
j/k # Move down/up in current panel (vim-style)
h/l # Move left/right between panels
G/g # Go to end/beginning of file
L # Go to line / show location
/ # Search in source code
, # Search previous
. # Search next
Ctrl-f/Ctrl-b # Page forward/backward
Ctrl-d/Ctrl-u # Half page down/up

# System commands
q / quit # Quit debugger
restart # Restart program
! # Open external shell
Ctrl-x # Built-in interactive shell / Evaluate expression
o # Show console/output screen
e # Show exception traceback
Ctrl-E # Edit current file with $EDITOR
Ctrl-p / Ctrl-P # Access preferences/themes

# Variable inspection
Enter # Expand/collapse variable in variables panel
\\ # Expand/collapse all variables recursively

# Special features
<Enter> # Repeat last command

Basic Debugging Workflow

1. Start Debugging Session

# In your code
import pudb; pudb.set_trace()

# Your code here
def calculate_total(items):
total = 0
for item in items:
total += item['price'] * item['quantity']
return total

2. Navigate the Interface

  1. Examine source code - The main panel shows your code with the current line highlighted
  2. Check variables - The variables panel shows current local and global variables
  3. Review call stack - The stack panel shows how you got to the current location
  4. Manage breakpoints - The breakpoints panel lists all active breakpoints

3. Step Through Code

  • Use n to step to the next line
  • Use s to step into function calls
  • Use c to continue until the next breakpoint
  • Use f to finish the current function

4. Inspect Data

  • Navigate to the variables panel with V
  • Use Enter to expand complex data structures
  • Use Ctrl+x to evaluate expressions interactively
  • Use / to search through the source code

Remote Debugging

pudb.remote enables debugging Python applications that don't have direct terminal access, such as web servers, background processes, GUI applications, or containerized applications. It creates a telnet-based debugging session that you can connect to from any terminal.

Key Benefits

  • Debug applications without stdin/stdout access - Web servers, background processes
  • Debug containerized applications from host system - Docker, Kubernetes debugging
  • Debug web servers without interrupting HTTP responses - Non-blocking debugging
  • Debug GUI applications without blocking the interface - Tkinter, PyQt applications
  • Debug remote servers over network connections - Production server debugging
  • Multiple concurrent debugging sessions - Different ports for different components

Basic Remote Debugging Setup

Method 1: Basic Remote Trace

from pudb.remote import set_trace
set_trace() # Default: localhost:6899

# Your application code continues here
process_data()

When set_trace() is called, PuDB will:

  1. Find a free port and start listening
  2. Display a message like: "Please start a telnet session using a command like: telnet 127.0.0.1 6899"
  3. Pause execution until a telnet connection is established
  4. Provide the full PuDB interface once connected

Connection:

telnet localhost 6899

Method 2: Custom Host and Port

from pudb.remote import set_trace
set_trace(term_size=(120, 40), host='0.0.0.0', port=6900)

# Application logic
run_application()

Advanced Configuration Options

Terminal Size Configuration

from pudb.remote import set_trace

# Method 1: Direct specification
set_trace(term_size=(columns, rows))

# Common terminal sizes
set_trace(term_size=(80, 24)) # Standard
set_trace(term_size=(120, 40)) # Wide
set_trace(term_size=(100, 30)) # Medium

# Method 2: Environment variable
import os
os.environ['PuDB_TERM_SIZE'] = '120,40'
set_trace() # Will use 120x40

Host and Port Configuration

from pudb.remote import set_trace

# Bind to all interfaces (allows external connections)
set_trace(host='0.0.0.0', port=6899)

# Use random available port
set_trace(port=0)

# Localhost only (secure)
set_trace(host='127.0.0.1', port=6899)

Real-World Use Cases

Web Application Debugging

# Flask application
from flask import Flask, request, jsonify
from pudb.remote import set_trace

app = Flask(__name__)

@app.route('/api/process', methods=['POST'])
def process_data():
# Debug without blocking HTTP response
set_trace(port=6899)

data = request.get_json()
result = complex_processing(data)

return jsonify(result)

if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)

Docker Container Debugging

# app.py in Docker container
from pudb.remote import set_trace

def main():
# Debug inside container, connect from host
set_trace(host='0.0.0.0', port=6899)

data = "item1,debug_item,item3"
result = process_application_data(data)

print(f"Application result: {result}")

if __name__ == '__main__':
main()

Security Considerations

from pudb.remote import set_trace

# SECURE: Only bind to localhost for local debugging
set_trace(host='127.0.0.1', port=6899)

# RECOMMENDED: Use SSH tunneling for remote access
# ssh -L 6899:localhost:6899 user@remote-server

Configuration

PuDB Configuration File

PuDB stores configuration in ~/.config/pudb/pudb.cfg:

[pudb]
theme = dark vim
line_numbers = True
variables_weight = 0.5
stack_weight = 0.3
breakpoints_weight = 0.2
sidebar_width = 0.5
wrap_variables = True
display = auto
stringifier = type
current_stack_frame = top

Available Themes

PuDB includes several built-in themes:

  • classic - Traditional PuDB colors
  • dark vim - Dark theme with vim-inspired colors
  • vim - Light vim-inspired theme
  • dark - Simple dark color scheme
  • light - Simple light color scheme
  • monokai - Popular Monokai color scheme
  • solarized - Solarized color scheme
  • midnight - Very dark theme for low-light environments

Changing Themes

Through Interface

  1. Press Ctrl-p or o to open preferences
  2. Navigate to theme selection
  3. Choose your preferred theme
  4. Changes are saved automatically

Environment-Based Configuration

import os
from pudb.remote import set_trace

# Only enable in development environments
if os.getenv('ENVIRONMENT') == 'development':
set_trace(port=6899)
elif os.getenv('ALLOW_DEBUG_STAGING') == 'true' and os.getenv('ENVIRONMENT') == 'staging':
# Restricted debugging in staging
set_trace(host='127.0.0.1', port=6899)
# Never enable in production without explicit override

Tutorials

Tutorial 1: Mastering the PuDB Interface

Learn to navigate PuDB's multi-panel interface effectively.

# tutorial_pudb_interface.py
class TaskManager:
def __init__(self):
self.tasks = []
self.completed = []
self.priority_map = {'low': 1, 'medium': 2, 'high': 3}

def add_task(self, description, priority='medium'):
import pudb; pudb.set_trace()

task = {
'id': len(self.tasks) + 1,
'description': description,
'priority': priority,
'priority_score': self.priority_map.get(priority, 2),
'status': 'pending'
}

self.tasks.append(task)
self._sort_tasks()
return task

def _sort_tasks(self):
self.tasks.sort(key=lambda x: x['priority_score'], reverse=True)

# Test the interface
manager = TaskManager()
manager.add_task("Learn PuDB interface", "high")

Interface Navigation Tutorial:

  1. Source Panel Navigation:

    • Use j/k to move line by line
    • Use G/g to go to end/beginning
    • Use L to jump to specific line number
    • Use / to search, then , and . for prev/next
  2. Variables Panel Inspection:

    • Press V to focus on variables panel
    • Use Enter to expand/collapse variables
    • Navigate with arrow keys or j/k
    • Press \\ to expand all variables
  3. Stack Panel Analysis:

    • Press S to focus on stack panel
    • Use u/d to move up/down frames
    • Press Enter to jump to frame location

Tutorial 2: Advanced Breakpoint Strategies

# tutorial_advanced_breakpoints.py
import pudb

def process_orders(orders):
results = []

for i, order in enumerate(orders):
# Conditional debugging based on order properties
if order.get('debug') or order.get('amount', 0) > 1000:
pudb.set_trace()

processed_order = validate_and_process_order(order, i)
results.append(processed_order)

return results

def validate_and_process_order(order, index):
# Debug specific order indices
if index in [3, 7, 12]: # Debug specific problematic orders
pudb.set_trace()

# Validation with conditional debugging
if not order.get('customer_id'):
pudb.set_trace() # Debug missing customer ID
raise ValueError(f"Missing customer_id in order {index}")

if order.get('amount', 0) < 0:
pudb.set_trace() # Debug negative amounts

processed = {
'order_id': order.get('id'),
'customer_id': order.get('customer_id'),
'amount': order.get('amount', 0),
'processed': True,
'index': index
}

return processed

Tutorial 3: Debugging Complex Data Structures

# tutorial_complex_objects.py
import pudb

class DataAnalyzer:
def __init__(self, dataset):
self.dataset = dataset
self.statistics = {}
self.results = []

def analyze(self):
pudb.set_trace() # Start debugging

# Complex nested data to inspect
for category, data in self.dataset.items():
category_stats = self._analyze_category(category, data)
self.statistics[category] = category_stats

return self.statistics

def _analyze_category(self, category, data):
# Debug point for category analysis
pudb.set_trace()

stats = {
'count': len(data),
'values': data,
'average': sum(data) / len(data) if data else 0,
'min': min(data) if data else None,
'max': max(data) if data else None
}

return stats

# Complex test data
test_data = {
'sales': [100, 150, 200, 175, 225],
'expenses': [50, 75, 100, 85, 110],
'profits': [50, 75, 100, 90, 115],
'customers': [10, 15, 20, 18, 22]
}

analyzer = DataAnalyzer(test_data)
results = analyzer.analyze()

Integration

Docker Integration

Dockerfile Configuration

FROM python:3.9
COPY . /app
WORKDIR /app

# Install debugging tools
RUN pip install pudb

# Expose debugging ports (range for multiple sessions)
EXPOSE 6899-6905

# Set environment for better debugging
ENV PYTHONUNBUFFERED=1
ENV PYTHONIOENCODING=utf-8

CMD ["python", "app.py"]

Docker Compose Configuration

version: '3.8'
services:
app:
build: .
ports:
- "6899:6899" # Main debug port
- "6900:6900" # Secondary debug port
- "6901:6901" # Background tasks
environment:
- ENABLE_REMOTE_DEBUG=true
- DEBUG_PORT=6899
- DEBUG_COLS=140
- DEBUG_ROWS=50
volumes:
- .:/app # For live code updates during debugging
tty: true
stdin_open: true

IDE Integration

VS Code Configuration

// .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File with PuDB",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"env": {
"PYTHONBREAKPOINT": "pudb.set_trace"
}
}
]
}

Testing Integration

pytest Integration

# conftest.py
import pytest
import os
import pudb

@pytest.fixture(autouse=True)
def debug_on_failure(request):
"""Automatically start debugger on test failure"""
yield

if request.node.rep_call.failed and os.getenv('PYTEST_DEBUG'):
pudb.set_trace()

@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
"""Store test results for debug_on_failure fixture"""
outcome = yield
rep = outcome.get_result()
setattr(item, "rep_" + rep.when, rep)

Best Practices

1. Use Specific Ports for Different Components

# Port assignment strategy
PORTS = {
'web_handler': 6899,
'background_worker': 6900,
'database_manager': 6901,
'api_client': 6902,
'data_processor': 6903
}

def debug_web_handler():
set_trace(port=PORTS['web_handler'])

2. Set Appropriate Terminal Size

# Different sizes for different use cases
TERMINAL_SIZES = {
'minimal': (80, 24),
'standard': (120, 40),
'wide': (140, 50),
'ultra_wide': (160, 60)
}

def debug_complex_data():
set_trace(term_size=TERMINAL_SIZES['wide'])

3. Use SSH Tunneling for Remote Servers

# Create persistent SSH tunnel
ssh -fN -L 6899:localhost:6899 user@remote-server.com

# Then connect locally
telnet localhost 6899

4. Configure for Production Safety

import os

def safe_debug():
"""Only allow debugging in development environments"""
if os.getenv('ENVIRONMENT') not in ['development', 'staging']:
print("Debugging disabled in production")
return

import pudb; pudb.set_trace()

5. Learn Keyboard Shortcuts

Essential shortcuts:

  • n - Next line
  • s - Step into
  • c - Continue
  • b - Toggle breakpoint
  • V - Variables panel
  • Ctrl+x - Evaluate expression
  • ? - Help
  • q - Quit

Further Reading

Official Documentation

Video Resources

Community Resources


PuDB transforms terminal-based debugging with its visual interface and powerful features—master it to debug Python applications more effectively in any environment.