Call stack profiler for Python that shows you why your code is slow
—
Primary profiling functionality providing the main interface for capturing and analyzing performance data. The Profiler class offers comprehensive control over profiling sessions with support for various execution modes and configuration options.
The main profiling interface that manages sampling configuration, session lifecycle, and basic output generation.
from typing import IO, Any, Literal
import sys
import os
import types
class Profiler:
"""
The main profiler class for capturing call stack profiles.
Attributes:
interval (float): Sampling interval in seconds
async_mode (AsyncMode): How to handle async/await code
last_session (Session | None): Most recent profiling session
is_running (bool): Whether profiler is currently active
"""
def __init__(
self,
interval: float = 0.001,
async_mode: AsyncMode = "enabled",
use_timing_thread: bool | None = None
):
"""
Initialize profiler with configuration options.
Args:
interval: Minimum time between samples in seconds (default: 0.001)
async_mode: How to handle async/await - "enabled", "disabled", or "strict"
use_timing_thread: Use separate thread for timing (helpful in some Docker environments)
"""
def start(
self,
caller_frame: types.FrameType | None = None,
target_description: str | None = None
) -> None:
"""
Start profiling session.
Args:
caller_frame: Override default caller frame detection
target_description: Description for this profiling session
Raises:
RuntimeError: If profiler is already running
"""
def stop(self) -> Session:
"""
Stop profiling and return captured session data.
Returns:
Session object containing profiling results
Raises:
RuntimeError: If profiler is not currently running
"""
def reset(self) -> None:
"""
Reset profiler state and clear last_session data.
"""
@property
def is_running(self) -> bool:
"""
Check if profiler is currently running.
Returns:
True if profiler is actively collecting samples, False otherwise
"""
def print(
self,
file: IO[str] = sys.stdout,
*,
unicode: bool | None = None,
color: bool | None = None,
show_all: bool = False,
timeline: bool = False,
time: Literal["seconds", "percent_of_total"] = "seconds",
flat: bool = False,
flat_time: FlatTimeMode = "self",
short_mode: bool = False,
processor_options: dict[str, Any] | None = None,
**kwargs
) -> None:
"""
Print profiling results to console.
Args:
file: Output stream (default: sys.stdout)
unicode: Use Unicode characters for display
color: Use ANSI color codes
show_all: Show all frames including library code
timeline: Show timeline view of execution
time: Display time as "seconds" or "percent_of_total"
flat: Show flat profile instead of call tree
flat_time: For flat mode - "self" or "cumulative" time
short_mode: Use compact output format
processor_options: Frame processing configuration
"""
def output_text(
self,
unicode: bool = False,
color: bool = False,
show_all: bool = False,
timeline: bool = False,
time: Literal["seconds", "percent_of_total"] = "seconds",
flat: bool = False,
flat_time: FlatTimeMode = "self",
short_mode: bool = False,
processor_options: dict[str, Any] | None = None
) -> str:
"""
Generate profiling results as formatted text string.
Args:
unicode: Use Unicode characters for display
color: Use ANSI color codes
show_all: Show all frames including library code
timeline: Show timeline view of execution
time: Display time as "seconds" or "percent_of_total"
flat: Show flat profile instead of call tree
flat_time: For flat mode - "self" or "cumulative" time
short_mode: Use compact output format
processor_options: Frame processing configuration
Returns:
Formatted profiling output as string
"""
def output_html(self) -> str:
"""
Generate profiling results as interactive HTML.
Returns:
HTML string with interactive profiling interface
"""
def write_html(
self,
path: str | os.PathLike[str],
timeline: bool = False,
show_all: bool = False
) -> None:
"""
Write HTML profiling results to file.
Args:
path: Output file path
timeline: Include timeline view
show_all: Show all frames including library code
"""
def open_in_browser(self, timeline: bool = False) -> None:
"""
Open profiling results in web browser.
Args:
timeline: Show timeline view
"""The Profiler class supports Python's context manager protocol for automatic session management.
def __enter__(self) -> Profiler:
"""
Enter context manager, automatically starting profiling.
Returns:
The Profiler instance for method chaining
"""
def __exit__(
self,
exc_type: type[BaseException] | None,
exc_value: BaseException | None,
traceback: types.TracebackType | None
) -> None:
"""
Exit context manager, automatically stopping profiling.
Args:
exc_type: Exception type if exception occurred
exc_value: Exception instance if exception occurred
traceback: Traceback object if exception occurred
"""from pyinstrument import Profiler
profiler = Profiler(interval=0.001) # Sample every 1ms
profiler.start()
# Your code to profile
result = expensive_calculation()
session = profiler.stop()
profiler.print()from pyinstrument import Profiler
with Profiler() as profiler:
# Code is automatically profiled
process_large_dataset()
# Results available in profiler.last_session# For async/await code
profiler = Profiler(async_mode="enabled")
# To disable async handling
profiler = Profiler(async_mode="disabled")
# Strict async context mode
profiler = Profiler(async_mode="strict")profiler = Profiler()
with profiler:
do_work()
# Different output formats
profiler.print(color=True, unicode=True, show_all=True)
html_output = profiler.output_html()
text_output = profiler.output_text(timeline=True)Install with Tessl CLI
npx tessl i tessl/pypi-pyinstrument