PyGuide

Learn Python with practical tutorials and code examples

Code Snippet Advanced
• Updated Jul 22, 2025

Python Can Error Frame Analysis Code Examples

Ready-to-use Python code snippets for error frame analysis when Python can error frame issues occur. Complete debugging examples and utilities.

Python Can Error Frame Analysis Code Examples

When Python can error frame issues occur in your applications, these ready-to-use code snippets help you analyze, debug, and handle frame-related problems effectively.

Basic Frame Information Extraction #

import sys
import traceback

def extract_error_frame_info():
    """Extract detailed information from error frames"""
    try:
        # Simulate an error
        result = 10 / 0
    except Exception as e:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        
        print("=== BASIC FRAME INFO ===")
        print(f"Exception type: {exc_type.__name__}")
        print(f"Exception value: {exc_value}")
        print(f"Traceback object: {exc_traceback}")
        
        # Get frame details
        frame = exc_traceback.tb_frame
        print(f"Function name: {frame.f_code.co_name}")
        print(f"Filename: {frame.f_code.co_filename}")
        print(f"Line number: {exc_traceback.tb_lineno}")
        print(f"Local variables: {list(frame.f_locals.keys())}")

# Usage
extract_error_frame_info()

Stack Trace Frame Walker #

import traceback
import sys

def walk_error_frames():
    """Walk through all frames in an error stack trace"""
    def level_3():
        return 1/0  # Error occurs here
    
    def level_2():
        return level_3()
    
    def level_1():
        return level_2()
    
    try:
        level_1()
    except ZeroDivisionError:
        print("=== WALKING ERROR FRAMES ===")
        exc_type, exc_value, exc_traceback = sys.exc_info()
        
        frame_num = 0
        tb = exc_traceback
        
        while tb is not None:
            frame = tb.tb_frame
            code = frame.f_code
            
            print(f"\nFrame #{frame_num}:")
            print(f"  Function: {code.co_name}")
            print(f"  File: {code.co_filename.split('/')[-1]}")
            print(f"  Line: {tb.tb_lineno}")
            print(f"  Local vars: {list(frame.f_locals.keys())}")
            
            frame_num += 1
            tb = tb.tb_next

# Usage
walk_error_frames()

Custom Frame Inspector Class #

import sys
import inspect
from typing import Dict, Any, List

class FrameInspector:
    """Utility class for inspecting Python error frames"""
    
    @staticmethod
    def get_current_frame_info() -> Dict[str, Any]:
        """Get information about the current frame"""
        frame = inspect.currentframe().f_back
        return {
            'function': frame.f_code.co_name,
            'filename': frame.f_code.co_filename.split('/')[-1],
            'line_number': frame.f_lineno,
            'local_vars': dict(frame.f_locals),
            'arg_names': frame.f_code.co_varnames
        }
    
    @staticmethod
    def extract_exception_frames(exception: Exception) -> List[Dict[str, Any]]:
        """Extract frame information from an exception"""
        frames = []
        tb = exception.__traceback__
        
        while tb is not None:
            frame = tb.tb_frame
            code = frame.f_code
            
            frame_info = {
                'function': code.co_name,
                'filename': code.co_filename.split('/')[-1],
                'line_number': tb.tb_lineno,
                'local_vars': dict(frame.f_locals),
                'code_context': FrameInspector._get_code_context(
                    code.co_filename, tb.tb_lineno
                )
            }
            frames.append(frame_info)
            tb = tb.tb_next
        
        return frames
    
    @staticmethod
    def _get_code_context(filename: str, line_number: int, context=3) -> List[str]:
        """Get code context around the error line"""
        try:
            with open(filename, 'r') as file:
                lines = file.readlines()
                start = max(0, line_number - context - 1)
                end = min(len(lines), line_number + context)
                return [line.rstrip() for line in lines[start:end]]
        except:
            return ["<code context not available>"]
    
    @staticmethod
    def print_frame_analysis(frames: List[Dict[str, Any]]):
        """Pretty print frame analysis"""
        print("=== FRAME ANALYSIS ===")
        for i, frame in enumerate(frames):
            print(f"\nFrame #{i}: {frame['function']}()")
            print(f"  File: {frame['filename']}:{frame['line_number']}")
            print(f"  Variables: {list(frame['local_vars'].keys())}")
            
            if frame['code_context']:
                print("  Code context:")
                for j, line in enumerate(frame['code_context']):
                    marker = " >> " if j == len(frame['code_context'])//2 else "    "
                    print(f"{marker}{line}")

# Usage example
def demo_frame_inspector():
    def problematic_function(x, y):
        data = {"x": x, "y": y}
        result = x / y  # Potential error
        return result
    
    try:
        result = problematic_function(10, 0)
    except Exception as e:
        frames = FrameInspector.extract_exception_frames(e)
        FrameInspector.print_frame_analysis(frames)

# Run the demo
demo_frame_inspector()

Error Context Capture Decorator #

import functools
import sys
from datetime import datetime

def capture_error_context(include_vars=True):
    """Decorator that captures detailed error context when exceptions occur"""
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except Exception as e:
                # Capture error context
                exc_type, exc_value, exc_traceback = sys.exc_info()
                
                error_context = {
                    'timestamp': datetime.now().isoformat(),
                    'function': func.__name__,
                    'exception_type': exc_type.__name__,
                    'exception_message': str(exc_value),
                    'args': args,
                    'kwargs': kwargs,
                    'frames': []
                }
                
                # Walk through frames
                tb = exc_traceback
                while tb is not None:
                    frame = tb.tb_frame
                    frame_info = {
                        'function': frame.f_code.co_name,
                        'filename': frame.f_code.co_filename.split('/')[-1],
                        'line_number': tb.tb_lineno,
                    }
                    
                    if include_vars:
                        # Filter out large objects for readability
                        local_vars = {}
                        for k, v in frame.f_locals.items():
                            try:
                                if len(str(v)) < 100:
                                    local_vars[k] = v
                                else:
                                    local_vars[k] = f"<{type(v).__name__}: too large>"
                            except:
                                local_vars[k] = f"<{type(v).__name__}: cannot display>"
                        
                        frame_info['local_vars'] = local_vars
                    
                    error_context['frames'].append(frame_info)
                    tb = tb.tb_next
                
                # Print the context
                print(f"\n=== ERROR CONTEXT [{error_context['timestamp']}] ===")
                print(f"Function: {error_context['function']}")
                print(f"Exception: {error_context['exception_type']}: {error_context['exception_message']}")
                
                print("\nCall Stack:")
                for i, frame in enumerate(error_context['frames']):
                    print(f"  {i+1}. {frame['function']}() in {frame['filename']}:{frame['line_number']}")
                    if 'local_vars' in frame and frame['local_vars']:
                        print(f"     Variables: {frame['local_vars']}")
                
                # Re-raise the exception
                raise
        
        return wrapper
    return decorator

# Usage example
@capture_error_context(include_vars=True)
def example_function(x, y, debug_mode=False):
    """Example function with error context capture"""
    temp_var = f"processing {x} and {y}"
    
    if debug_mode:
        print(f"Debug: {temp_var}")
    
    # This might cause an error
    result = x / y
    return result

# Test the decorator
try:
    result = example_function(10, 0, debug_mode=True)
except ZeroDivisionError:
    print("Error was handled and context was captured")

Memory-Efficient Frame Inspector #

import sys
from typing import Generator, Dict, Any

class LightweightFrameInspector:
    """Memory-efficient frame inspector for production use"""
    
    @staticmethod
    def inspect_exception_lightweight(exception: Exception) -> Generator[Dict[str, Any], None, None]:
        """Generator that yields frame info without storing all frames in memory"""
        tb = exception.__traceback__
        frame_count = 0
        
        while tb is not None:
            frame = tb.tb_frame
            code = frame.f_code
            
            # Yield minimal frame info
            yield {
                'frame_number': frame_count,
                'function': code.co_name,
                'filename': code.co_filename.split('/')[-1],
                'line_number': tb.tb_lineno,
                'arg_count': code.co_argcount,
                'var_names': code.co_varnames[:code.co_argcount]
            }
            
            frame_count += 1
            tb = tb.tb_next
    
    @staticmethod
    def get_error_summary(exception: Exception) -> Dict[str, Any]:
        """Get a concise error summary for logging"""
        frames = list(LightweightFrameInspector.inspect_exception_lightweight(exception))
        
        return {
            'exception_type': type(exception).__name__,
            'message': str(exception),
            'frame_count': len(frames),
            'entry_point': frames[0]['function'] if frames else 'unknown',
            'error_location': f"{frames[-1]['filename']}:{frames[-1]['line_number']}" if frames else 'unknown',
            'call_chain': [f"{frame['function']}()" for frame in frames]
        }

# Usage example
def demonstrate_lightweight_inspection():
    def deep_function_3():
        return 1 / 0
    
    def deep_function_2():
        return deep_function_3()
    
    def deep_function_1():
        return deep_function_2()
    
    try:
        deep_function_1()
    except ZeroDivisionError as e:
        # Lightweight inspection
        summary = LightweightFrameInspector.get_error_summary(e)
        print("=== LIGHTWEIGHT FRAME INSPECTION ===")
        print(f"Error: {summary['exception_type']}: {summary['message']}")
        print(f"Frames: {summary['frame_count']}")
        print(f"Entry point: {summary['entry_point']}")
        print(f"Error location: {summary['error_location']}")
        print(f"Call chain: {' -> '.join(summary['call_chain'])}")

# Run demonstration
demonstrate_lightweight_inspection()

Production Error Logger #

import json
import logging
import sys
from datetime import datetime
from pathlib import Path

class ProductionErrorLogger:
    """Production-ready error logger with frame context"""
    
    def __init__(self, log_file="error_frames.log", max_frame_vars=5):
        self.log_file = Path(log_file)
        self.max_frame_vars = max_frame_vars
        
        logging.basicConfig(level=logging.ERROR, format='%(asctime)s - %(levelname)s - %(message)s')
        self.logger = logging.getLogger(__name__)
    
    def log_exception_with_frames(self, exception: Exception, context: dict = None):
        """Log exception with detailed frame information"""
        error_data = {
            'timestamp': datetime.now().isoformat(),
            'exception_type': type(exception).__name__,
            'exception_message': str(exception),
            'context': context or {},
            'frames': self._extract_safe_frame_data(exception)
        }
        
        # Log to file
        with open(self.log_file, 'a') as f:
            json.dump(error_data, f, indent=2, default=str)
            f.write('\n' + '='*50 + '\n')
        
        self.logger.error(f"Exception logged: {type(exception).__name__}: {exception}")
    
    def _extract_safe_frame_data(self, exception: Exception) -> list:
        """Safely extract frame data without causing memory issues"""
        frames = []
        tb = exception.__traceback__
        
        while tb is not None:
            frame = tb.tb_frame
            code = frame.f_code
            
            # Get limited local variables
            safe_locals = {}
            var_count = 0
            
            for name, value in frame.f_locals.items():
                if var_count >= self.max_frame_vars:
                    safe_locals['...'] = f"and {len(frame.f_locals) - var_count} more variables"
                    break
                
                try:
                    if isinstance(value, (str, int, float, bool, type(None))):
                        if isinstance(value, str) and len(value) > 100:
                            safe_locals[name] = value[:100] + "..."
                        else:
                            safe_locals[name] = value
                    else:
                        safe_locals[name] = f"<{type(value).__name__}>"
                except:
                    safe_locals[name] = "<cannot serialize>"
                
                var_count += 1
            
            frame_data = {
                'function': code.co_name,
                'filename': Path(code.co_filename).name,
                'line_number': tb.tb_lineno,
                'local_variables': safe_locals
            }
            
            frames.append(frame_data)
            tb = tb.tb_next
        
        return frames

# Usage context manager
class ErrorFrameCapture:
    """Context manager for capturing error frames"""
    
    def __init__(self, logger: ProductionErrorLogger = None, context: dict = None):
        self.logger = logger or ProductionErrorLogger()
        self.context = context or {}
    
    def __enter__(self):
        return self
    
    def __exit__(self, exc_type, exc_value, exc_traceback):
        if exc_value:
            self.logger.log_exception_with_frames(exc_value, self.context)
        return False  # Don't suppress the exception

# Usage examples
def demo_production_logging():
    """Demonstrate production error logging"""
    logger = ProductionErrorLogger()
    
    # Example 1: Direct logging
    try:
        data = [1, 2, 3]
        result = data[10]  # IndexError
    except IndexError as e:
        logger.log_exception_with_frames(e, {'operation': 'list_access', 'list_length': len(data)})
    
    # Example 2: Context manager
    with ErrorFrameCapture(logger, {'operation': 'division', 'user_id': 12345}):
        x = 10
        y = 0
        result = x / y  # ZeroDivisionError

    print(f"Errors logged to: {logger.log_file}")

# Run the demo
demo_production_logging()

Interactive Frame Debugger #

import sys
import code
import traceback

def interactive_frame_debugger():
    """Interactive debugger that lets you inspect frames"""
    
    def problematic_code():
        x = [1, 2, 3]
        y = {"key": "value"}
        z = "debugging"
        
        # Simulate complex nested calls
        return nested_call_1(x, y, z)
    
    def nested_call_1(a, b, c):
        temp = len(a)
        return nested_call_2(a, b, c, temp)
    
    def nested_call_2(a, b, c, d):
        # Error occurs here
        return a[10]  # IndexError
    
    try:
        result = problematic_code()
    except Exception as e:
        print("=== INTERACTIVE FRAME DEBUGGER ===")
        print(f"Exception: {type(e).__name__}: {e}")
        print("\nAvailable commands:")
        print("  frames() - show all frames")
        print("  frame(n) - inspect frame n")
        print("  vars(n) - show variables in frame n")
        print("  code(n) - show code context for frame n")
        print("  exit() - exit debugger")
        
        # Get exception info
        exc_type, exc_value, exc_traceback = sys.exc_info()
        
        # Store frames for inspection
        frames_data = []
        tb = exc_traceback
        frame_num = 0
        
        while tb is not None:
            frames_data.append({
                'frame': tb.tb_frame,
                'line_number': tb.tb_lineno,
                'frame_num': frame_num
            })
            tb = tb.tb_next
            frame_num += 1
        
        def frames():
            """Show all frames in the stack"""
            for i, frame_data in enumerate(frames_data):
                frame = frame_data['frame']
                print(f"Frame {i}: {frame.f_code.co_name}() "
                      f"line {frame_data['line_number']}")
        
        def frame(n):
            """Show details for frame n"""
            if 0 <= n < len(frames_data):
                frame = frames_data[n]['frame']
                print(f"Frame {n}: {frame.f_code.co_name}()")
                print(f"File: {frame.f_code.co_filename}")
                print(f"Line: {frames_data[n]['line_number']}")
            else:
                print(f"Invalid frame number {n}")
        
        def vars(n):
            """Show variables for frame n"""
            if 0 <= n < len(frames_data):
                frame = frames_data[n]['frame']
                print(f"Variables in frame {n}:")
                for name, value in frame.f_locals.items():
                    try:
                        print(f"  {name} = {repr(value)}")
                    except:
                        print(f"  {name} = <cannot display>")
            else:
                print(f"Invalid frame number {n}")
        
        def code(n):
            """Show code context for frame n"""
            if 0 <= n < len(frames_data):
                frame = frames_data[n]['frame']
                filename = frame.f_code.co_filename
                line_number = frames_data[n]['line_number']
                
                try:
                    with open(filename, 'r') as f:
                        lines = f.readlines()
                        start = max(0, line_number - 3)
                        end = min(len(lines), line_number + 3)
                        
                        for i in range(start, end):
                            marker = ">>>" if i + 1 == line_number else "   "
                            print(f"{marker} {i+1:3d}: {lines[i].rstrip()}")
                except:
                    print("Cannot read source file")
            else:
                print(f"Invalid frame number {n}")
        
        # Start interactive session
        local_vars = {
            'frames': frames,
            'frame': frame,
            'vars': vars,
            'code': code,
            'frames_data': frames_data,
            'exception': exc_value
        }
        
        console = code.InteractiveConsole(locals=local_vars)
        console.interact("Interactive frame debugger ready (type exit() to quit):")

# Run interactive debugger
interactive_frame_debugger()

Frame Performance Monitor #

import time
import functools
import sys

def frame_performance_monitor(func):
    """Decorator that monitors function performance and frame context"""
    
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        frame = sys._getframe()
        
        try:
            result = func(*args, **kwargs)
            execution_time = time.time() - start_time
            
            print(f"Performance Report:")
            print(f"  Function: {func.__name__}")
            print(f"  Execution time: {execution_time:.4f} seconds")
            print(f"  Called from: {frame.f_back.f_code.co_name}")
            print(f"  Arguments: {len(args)} args, {len(kwargs)} kwargs")
            
            return result
        except Exception as e:
            execution_time = time.time() - start_time
            print(f"Function {func.__name__} failed after {execution_time:.4f}s")
            print(f"Error: {type(e).__name__}: {e}")
            
            # Capture frame context for error analysis
            exc_type, exc_value, exc_traceback = sys.exc_info()
            print("Error frame context:")
            tb = exc_traceback
            while tb:
                frame = tb.tb_frame
                print(f"  {frame.f_code.co_name} in {frame.f_code.co_filename.split('/')[-1]}:{tb.tb_lineno}")
                tb = tb.tb_next
            
            raise
    
    return wrapper

# Usage example
@frame_performance_monitor
def slow_function(n):
    """Example function that might be slow"""
    import time
    time.sleep(0.1)  # Simulate slow operation
    
    if n < 0:
        raise ValueError("n must be non-negative")
    
    return sum(range(n))

# Test the monitor
try:
    result = slow_function(100)
    print(f"Result: {result}")
    
    # Test with error
    result = slow_function(-1)
except ValueError:
    print("Error handling completed")

Usage Tips #

When to Use These Snippets #

  1. Basic frame extraction: Simple debugging and error investigation
  2. Stack trace walker: Understanding complex call chains
  3. Frame inspector class: Reusable debugging utilities
  4. Error context decorator: Automatic error context capture
  5. Lightweight inspector: Production environments with memory constraints
  6. Production logger: Enterprise applications requiring detailed error logs
  7. Interactive debugger: Development environments for deep investigation
  8. Performance monitor: Performance debugging with frame context

Performance Considerations #

  • Frame inspection adds overhead - use judiciously in production
  • Limit variable data captured to prevent memory issues
  • Use generators for large call stacks
  • Consider memory-efficient alternatives for long-running applications

Best Practices #

  • Clean up frame references to prevent memory leaks
  • Use context managers for automatic resource cleanup
  • Filter sensitive data when logging frame information
  • Implement configurable verbosity levels for production use

These code snippets provide comprehensive tools for when Python can error frame analysis is needed, helping you debug issues effectively while maintaining good performance characteristics.

Related Snippets

Snippet Intermediate

Python Error Frame Inspection Code Examples

Ready-to-use Python code snippets for inspecting error frames, analyzing stack traces, and debugging frame-related issues effectively.

#python #error #frame +2
View Code
Syntax
Snippet Intermediate

Python Error Handling Code Snippets: Try-Except Examples

Ready-to-use Python error handling code snippets. Copy-paste examples for common error handling patterns and exception management.

#python #error #exception +2
View Code
Syntax
Snippet Beginner

Python Indentation Error Fix Beginner Debugging Code Utilities

Ready-to-use Python code utilities for indentation error fix beginner debugging tips including detection scripts and automated fixing tools.

#python #indentation #debugging +3
View Code
Syntax
Snippet Intermediate

Python What Error to Raise: Code Examples and Patterns

Practical code snippets showing what error to raise in Python. Copy-paste examples for ValueError, TypeError, AttributeError, and custom exceptions.

#python #exceptions #raise +2
View Code
Syntax