Python's missing debug print command and development tools with enhanced debugging, pretty printing, timing, and ANSI styling capabilities.
—
Enhanced debug printing system that automatically extracts variable names, displays types and metadata, shows source location, and provides syntax highlighting with intelligent pretty formatting. The debug system uses the executing library to inspect the call stack and extract variable names from the source code.
The main debug function automatically extracts variable names from source code and displays them with their values, types, and additional metadata.
def debug(*args, file_=None, flush_=True, frame_depth_=2, **kwargs):
"""
Debug print with automatic variable name extraction and context.
Parameters:
- *args: Variables to debug print
- file_: Output file (default: stdout)
- flush_: Flush output buffer (default: True)
- frame_depth_: Stack frame depth for inspection (default: 2)
- **kwargs: Named variables to debug print
Returns:
Single arg: returns the argument itself
Multiple args: returns tuple of arguments
With kwargs: returns (*args, kwargs)
"""Usage examples:
from devtools import debug
# Basic variable debugging
name = "Alice"
age = 30
debug(name, age)
# Output: example.py:5 <module>:
# name: 'Alice' (str) len=5
# age: 30 (int)
# Debug complex data structures
data = {'users': [1, 2, 3], 'config': {'debug': True}}
debug(data)
# Output: example.py:9 <module>:
# data: {
# 'users': [1, 2, 3],
# 'config': {'debug': True},
# } (dict) len=2
# Debug with expressions
numbers = [1, 2, 3, 4, 5]
debug(len(numbers), sum(numbers))
# Output: example.py:13 <module>:
# len(numbers): 5 (int)
# sum(numbers): 15 (int)
# Named keyword arguments
debug(total=sum(numbers), average=sum(numbers)/len(numbers))
# Output: example.py:15 <module>:
# total: 15 (int)
# average: 3.0 (float)Configurable debug class that allows customization of warning display and syntax highlighting behavior.
class Debug:
"""
Configurable debug print class.
"""
def __init__(self, warnings=None, highlight=None):
"""
Initialize Debug instance.
Parameters:
- warnings: Show warnings (None uses PY_DEVTOOLS_WARNINGS env var, default True)
- highlight: Enable syntax highlighting (None uses auto-detection)
"""
def __call__(self, *args, file_=None, flush_=True, frame_depth_=2, **kwargs):
"""
Debug print with automatic variable name extraction.
Parameters:
- *args: Variables to debug print
- file_: Output file (default: stdout)
- flush_: Flush output buffer (default: True)
- frame_depth_: Stack frame depth for inspection (default: 2)
- **kwargs: Named variables to debug print
Returns:
Single arg: the arg itself
Multiple args: tuple of args
With kwargs: (*args, kwargs)
"""
def format(self, *args, frame_depth_=2, **kwargs) -> DebugOutput:
"""
Format debug output without printing.
Parameters:
- *args: Variables to format
- frame_depth_: Stack frame depth for inspection (default: 2)
- **kwargs: Named variables to format
Returns:
DebugOutput object containing formatted debug information
"""
def breakpoint(self) -> None:
"""
Set a breakpoint using pdb, skipping devtools frames.
"""
def timer(self, name=None, verbose=True, file=None, dp=3) -> Timer:
"""
Create and return a Timer instance.
Parameters:
- name: Timer name (optional)
- verbose: Print timing results (default: True)
- file: Output file (default: stdout)
- dp: Decimal places for timing display (default: 3)
Returns:
Timer instance configured with the specified parameters
"""Usage examples:
from devtools import Debug
# Create custom debug instance without warnings
quiet_debug = Debug(warnings=False)
quiet_debug(some_variable)
# Create debug instance with forced highlighting
colored_debug = Debug(highlight=True)
colored_debug(data_structure)
# Format without printing
debug_output = debug.format(variable_name)
formatted_string = debug_output.str(highlight=True)
print(f"Custom prefix: {formatted_string}")
# Use integrated timer
with debug.timer('operation'):
# Some code to time
passClasses representing formatted debug output and individual arguments.
class DebugOutput:
"""
Represents formatted debug output containing file context and arguments.
"""
def __init__(self, filename: str, lineno: int, frame: str, arguments: list[DebugArgument], warning: str | bool | None = None):
"""
Initialize DebugOutput.
Parameters:
- filename: Source file path
- lineno: Line number in source file
- frame: Function/method name
- arguments: List of DebugArgument instances
- warning: Warning message or None
"""
def str(self, highlight: bool = False) -> str:
"""
Format debug output as string.
Parameters:
- highlight: Apply syntax highlighting
Returns:
Formatted debug output string
"""
def __str__(self) -> str:
"""String representation of debug output."""
def __repr__(self) -> str:
"""Detailed representation for debugging."""
class DebugArgument:
"""
Represents a single debug argument with name, value, and metadata.
"""
def __init__(self, value, name: str | None = None, **extra):
"""
Initialize DebugArgument.
Parameters:
- value: The argument value
- name: Variable name (extracted from source)
- **extra: Additional metadata (e.g., length for sequences)
"""
def str(self, highlight: bool = False) -> str:
"""
Format argument as string.
Parameters:
- highlight: Apply syntax highlighting
Returns:
Formatted argument string with name, value, type, and metadata
"""
def __str__(self) -> str:
"""String representation of debug argument."""The debug system integrates seamlessly with devtools' pretty printing capabilities:
# Debug automatically uses pretty printing for complex structures
nested_data = {
'level1': {
'level2': ['item1', 'item2', 'item3'],
'numbers': list(range(10))
}
}
debug(nested_data)
# Output shows nicely formatted nested structure with proper indentationThe debug system gracefully handles various error conditions:
# Debug works even when code inspection fails
debug(some_variable) # May show warning but still displays the valueDebug behavior can be customized via environment variables:
PY_DEVTOOLS_WARNINGS: Show/hide warnings (default: True)PY_DEVTOOLS_HIGHLIGHT: Force highlighting on/offPY_DEVTOOLS_INDENT: Indentation for pretty printing (default: 4)PY_DEVTOOLS_WIDTH: Output width (default: 120)# Main debug instance - pre-configured Debug() instance
debug: Debug
# Type aliases used internally
StrType = str # String type alias for type hintingInstall with Tessl CLI
npx tessl i tessl/pypi-devtools