or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/pypi-pysnooper

A poor man's debugger for Python that provides elegant tracing without print statements.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/pysnooper@1.2.x

To install, run

npx @tessl/cli install tessl/pypi-pysnooper@1.2.0

index.mddocs/

PySnooper

A poor man's debugger for Python that provides elegant tracing without print statements. PySnooper offers an alternative to traditional debugging with breakpoints by decorating functions or wrapping code blocks to get detailed execution logs showing line-by-line execution, variable changes, and timing information.

Package Information

  • Package Name: PySnooper
  • Language: Python
  • Installation: pip install pysnooper

Core Imports

import pysnooper

Basic Usage

import pysnooper

# Decorator usage - trace entire function
@pysnooper.snoop()
def number_to_bits(number):
    if number:
        bits = []
        while number:
            number, remainder = divmod(number, 2)
            bits.insert(0, remainder)
        return bits
    else:
        return [0]

# Context manager usage - trace code block
def analyze_data():
    data = [1, 2, 3, 4, 5]
    
    with pysnooper.snoop():
        minimum = min(data)
        maximum = max(data)
        average = sum(data) / len(data)
        
    return minimum, maximum, average

# Output redirection to file
@pysnooper.snoop('/tmp/debug.log')
def process_data(items):
    result = []
    for item in items:
        result.append(item * 2)
    return result

Capabilities

Main Tracing Decorator

The primary debugging interface that can be used as both a decorator and context manager.

class snoop:
    def __init__(
        self,
        output=None,
        watch=(),
        watch_explode=(),
        depth=1,
        prefix='',
        overwrite=False,
        thread_info=False,
        custom_repr=(),
        max_variable_length=100,
        normalize=False,
        relative_time=False,
        color=True
    ):
        """
        Snoop on function execution, writing detailed logs to output.
        
        Args:
            output: Output destination - None (stderr), file path, stream, or callable
            watch (tuple): Expressions to watch that aren't local variables
            watch_explode (tuple): Expressions to expand/explode (show attributes/items)
            depth (int): Tracing depth for nested function calls (default: 1)
            prefix (str): Prefix string for all snoop output lines
            overwrite (bool): Whether to overwrite output file (default: False)
            thread_info (bool): Include thread information in output
            custom_repr (tuple): Custom representation functions for objects
            max_variable_length (int): Maximum length for variable representations (default: 100)
            normalize (bool): Remove machine-specific data (paths, addresses, timestamps)
            relative_time (bool): Show timestamps relative to start time
            color (bool): Enable colored output (default: True on Linux/macOS)
        """
    
    def __call__(self, function_or_class):
        """Use as decorator on functions or classes."""
    
    def __enter__(self):
        """Use as context manager - enter tracing block."""
    
    def __exit__(self, exc_type, exc_value, exc_traceback):
        """Use as context manager - exit tracing block."""

Variable Helper Classes

Helper classes for advanced variable watching and expansion.

class Attrs:
    def __init__(self, source, exclude=()):
        """
        Watch object attributes.
        
        Args:
            source (str): Variable expression to watch
            exclude (tuple): Attribute names to exclude from watching
        """

class Keys:
    def __init__(self, source, exclude=()):
        """
        Watch dictionary/mapping keys and values.
        
        Args:
            source (str): Variable expression to watch
            exclude (tuple): Keys to exclude from watching
        """

class Indices:
    def __init__(self, source, exclude=()):
        """
        Watch sequence indices and values with optional slicing.
        
        Args:
            source (str): Variable expression to watch
            exclude (tuple): Indices to exclude from watching
        """
    
    def __getitem__(self, slice_obj):
        """
        Enable slicing syntax like Indices('list_var')[1:5].
        
        Args:
            slice_obj (slice): Slice object for limiting indices
            
        Returns:
            Indices: New Indices instance with slice applied
        """

class Exploding:
    def __init__(self, source, exclude=()):
        """
        Smart variable expander - automatically determines expansion method.
        
        Args:
            source (str): Variable expression to watch
            exclude (tuple): Items to exclude from watching
        
        Behavior:
            - Uses Keys for mappings (dict-like objects)
            - Uses Indices for sequences (list-like objects) 
            - Uses Attrs for other objects
        """

Module Metadata

Version information for the package.

__version__: str
    # Version string (e.g., '1.2.3')

__version_info__: NamedTuple
    # Structured version information with major, minor, micro fields

Usage Examples

File Output

Redirect tracing output to a file:

@pysnooper.snoop('/my/log/file.log')
def process_data(data):
    return [x * 2 for x in data]

Watching Expressions

Monitor specific expressions that aren't local variables:

@pysnooper.snoop(watch=('len(data)', 'data[0]', 'self.status'))
def analyze_list(self, data):
    # Will show values of watched expressions
    result = sum(data)
    return result

Variable Expansion

Expand objects to see their attributes or items:

# Automatic expansion
@pysnooper.snoop(watch_explode=('obj', 'data_dict'))
def process_object(obj, data_dict):
    return obj.process(data_dict)

# Specific expansion types
@pysnooper.snoop(watch=(
    pysnooper.Attrs('obj'),           # Object attributes
    pysnooper.Keys('data_dict'),      # Dictionary keys/values
    pysnooper.Indices('items')[2:5],  # List items with slicing
))
def detailed_processing(obj, data_dict, items):
    return obj.transform(data_dict, items)

Deep Tracing

Show snoop lines for functions called within traced functions:

@pysnooper.snoop(depth=2)
def main_function():
    helper_function()  # This will also be traced
    return "done"

def helper_function():
    x = 42
    return x * 2

Multi-threading Support

Identify threads in multi-threaded applications:

@pysnooper.snoop(thread_info=True)
def worker_function(task_id):
    # Output will include thread information
    return process_task(task_id)

Custom Output Formatting

Customize how values are displayed:

def custom_list_repr(obj):
    if isinstance(obj, list) and len(obj) > 10:
        return f'list(len={len(obj)})'
    return repr(obj)

@pysnooper.snoop(
    custom_repr=((lambda x: isinstance(x, list), custom_list_repr),),
    max_variable_length=200,
    prefix='DEBUG: ',
    color=False
)
def process_large_data(big_list):
    return sum(big_list)

Class Decoration

Trace all methods in a class:

@pysnooper.snoop()
class DataProcessor:
    def __init__(self, data):
        self.data = data
    
    def process(self):
        return [x * 2 for x in self.data]
    
    def analyze(self):
        return sum(self.data)

Environment Variables

PYSNOOPER_DISABLED

Disable all PySnooper tracing globally:

export PYSNOOPER_DISABLED=1

When set, all @pysnooper.snoop() decorators and context managers become no-ops.

Error Handling

PySnooper is designed to be non-intrusive. If tracing encounters errors:

  • Variable evaluation failures are silently ignored
  • File output errors fall back to stderr
  • Internal exceptions don't interrupt program execution

The traced code continues running normally even if tracing fails.

Advanced Features

Generator Support

PySnooper automatically detects and properly handles generator functions:

@pysnooper.snoop()
def fibonacci_generator(n):
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b

Lambda and Inline Function Support

Works with lambda functions and dynamically created functions:

# Trace lambda execution
traced_lambda = pysnooper.snoop()(lambda x: x * 2)
result = traced_lambda(5)

Context Manager Timing

Context manager usage shows elapsed time for code blocks:

def analyze_performance():
    data = list(range(1000))
    
    with pysnooper.snoop():
        # This block will show execution time
        result = sum(x * x for x in data)
        
    return result