CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pyinstrument

Call stack profiler for Python that shows you why your code is slow

Pending
Overview
Eval results
Files

framework-integration.mddocs/

Framework Integration

Built-in integration capabilities for popular Python frameworks and development environments including Jupyter notebooks, IPython magic commands, command-line usage, and decorator/context manager patterns for easy adoption.

Capabilities

Jupyter/IPython Integration

Magic commands for interactive profiling in Jupyter notebooks and IPython shells with support for cell-level and line-level profiling.

def load_ipython_extension(ipython):
    """
    Load pyinstrument IPython extension for magic commands.
    
    Usage in IPython/Jupyter:
        %load_ext pyinstrument
    
    Args:
        ipython: IPython instance to register magic commands with
    """

class PyinstrumentMagic:
    """
    IPython magic commands for profiling code in interactive environments.
    
    Available magics:
        %pyinstrument - Profile a single line of code
        %%pyinstrument - Profile an entire cell
    """
    
    @line_cell_magic
    def pyinstrument(self, line: str, cell: str | None = None):
        """
        Profile code execution with various output options.
        
        Line magic: %pyinstrument code_to_profile()
        Cell magic: %%pyinstrument
                   code_to_profile()
                   more_code()
        
        Options:
            -p, --render-option: Renderer options (flag_name or option_name=option_value)
            --show-regex: Regex matching file paths whose frames to always show
            --show: Glob-style pattern matching file paths to show
            --interval: Sampling interval in seconds (default: 0.001)
            --show-all: Show all frames including root and internal IPython frames
            --async_mode: Async handling mode (disabled, enabled, strict, default: disabled)
            --height: Output height for HTML renderer (default: 400)
            --timeline: Show timeline view (default: False)
        """

Context Manager and Decorator

Convenient decorator and context manager interfaces for easy integration with existing code.

class ProfileContext:
    """Context manager and decorator for profiling code blocks."""
    
    def __init__(
        self,
        interval: float = 0.001,
        async_mode: AsyncMode = "disabled",
        use_timing_thread: bool | None = None,
        renderer: Renderer | None = None,
        target_description: str | None = None
    ):
        """
        Initialize profiling context.
        
        Args:
            interval: Sampling interval in seconds
            async_mode: Async handling mode
            use_timing_thread: Use separate timing thread
            renderer: Output renderer (defaults to ConsoleRenderer)
            target_description: Description for profiling session
        """
    
    def __call__(self, func: Callable | None = None, /, **kwargs):
        """
        Use as decorator or create new context with updated options.
        
        As decorator:
            @profile
            def my_function():
                pass
                
        With options:
            @profile(interval=0.005, renderer=HTMLRenderer())
            def my_function():
                pass
        """
    
    def __enter__(self):
        """Enter context manager and start profiling."""
    
    def __exit__(self, exc_type, exc_value, traceback):
        """Exit context manager, stop profiling, and display results."""

def profile(**kwargs) -> ProfileContext:
    """
    Create a profiling context manager or decorator.
    
    Usage as context manager:
        with profile():
            code_to_profile()
            
    Usage as decorator:
        @profile
        def function_to_profile():
            pass
    
    Args:
        **kwargs: Configuration options passed to ProfileContext
        
    Returns:
        ProfileContext instance
    """

Command Line Interface

Complete command-line interface for profiling Python scripts and modules.

def main():
    """
    Main entry point for pyinstrument command-line interface.
    
    Usage:
        pyinstrument script.py [args...]
        python -m pyinstrument script.py [args...]
        
    Options:
        --interval: Sampling interval in seconds
        --async-mode: Async handling mode
        --renderer: Output format (text, html, json, speedscope)
        --outfile: Output file path
        --show-all: Show all frames including library code
        --timeline: Show timeline view (HTML renderer)
        --unicode: Use Unicode characters in console output
        --color: Use color in console output
    """

Usage Examples

Jupyter Notebook Magic Commands

# Load the extension
%load_ext pyinstrument

# Profile a single line
%pyinstrument expensive_function()

# Profile a cell with options
%%pyinstrument --renderer=html --render-option=timeline=true
data = load_large_dataset()
result = process_data(data)
visualize_results(result)

# Profile async code
%%pyinstrument --async_mode=enabled
await async_data_processing()

Decorator Usage

from pyinstrument import profile

# Simple decorator
@profile
def data_analysis():
    load_data()
    process_data()
    generate_report()

data_analysis()  # Results automatically printed

# Decorator with options
@profile(renderer=HTMLRenderer(timeline=True))
def complex_computation():
    matrix_operations()
    statistical_analysis()

complex_computation()

Context Manager with Custom Renderer

from pyinstrument import profile
from pyinstrument.renderers import HTMLRenderer

# Custom renderer context
html_renderer = HTMLRenderer(timeline=True, show_all=False)

with profile(renderer=html_renderer):
    machine_learning_training()
    model_evaluation()

Command Line Profiling

# Basic script profiling
pyinstrument my_script.py

# With options
pyinstrument --renderer=html --outfile=profile.html my_script.py

# Module profiling
python -m pyinstrument -m my_module

# With timeline view
pyinstrument --timeline --renderer=html --outfile=timeline.html script.py

# JSON output for analysis
pyinstrument --renderer=json --outfile=profile.json script.py

Django Integration

# Django middleware example
from pyinstrument import Profiler
from django.conf import settings

class ProfilerMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        if settings.DEBUG and 'profile' in request.GET:
            profiler = Profiler()
            profiler.start()
            
            response = self.get_response(request)
            
            profiler.stop()
            
            # Add profile to response
            if request.GET.get('format') == 'html':
                response.content = profiler.output_html().encode()
                response['Content-Type'] = 'text/html'
            else:
                profiler.print()
                
            return response
        
        return self.get_response(request)

FastAPI Integration

from fastapi import FastAPI, Request
from pyinstrument import Profiler

app = FastAPI()

@app.middleware("http")
async def profile_middleware(request: Request, call_next):
    if request.query_params.get("profile"):
        profiler = Profiler(async_mode="enabled")
        profiler.start()
        
        response = await call_next(request)
        
        profiler.stop()
        
        # Return profile as HTML
        if request.query_params.get("format") == "html":
            html = profiler.output_html()
            return Response(content=html, media_type="text/html")
        else:
            profiler.print()
            
        return response
    
    return await call_next(request)

Programmatic Integration

from pyinstrument import Profiler
from pyinstrument.renderers import JSONRenderer
import json

def profile_and_analyze(func, *args, **kwargs):
    """Profile a function call and return structured results."""
    profiler = Profiler()
    
    profiler.start()
    result = func(*args, **kwargs)
    profiler.stop()
    
    # Get structured profiling data
    json_renderer = JSONRenderer()
    profile_data = json.loads(json_renderer.render(profiler.last_session))
    
    return {
        'function_result': result,
        'profile_data': profile_data,
        'execution_time': profiler.last_session.duration,
        'cpu_time': profiler.last_session.cpu_time
    }

# Usage
analysis = profile_and_analyze(expensive_computation, data_param)
print(f"Execution took {analysis['execution_time']:.3f} seconds")

Types

AsyncMode = Literal["enabled", "disabled", "strict"]

class Renderer:
    """Base renderer interface for output formatting."""
    def render(self, session: Session) -> str: ...

ProfileContextOptions = TypedDict("ProfileContextOptions", {
    "interval": float,
    "async_mode": AsyncMode,
    "use_timing_thread": bool | None,
    "renderer": Renderer | None,
    "target_description": str | None,
}, total=False)

Install with Tessl CLI

npx tessl i tessl/pypi-pyinstrument

docs

core-profiling.md

framework-integration.md

index.md

output-rendering.md

session-management.md

tile.json