CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-py-spy

Sampling profiler for Python programs written in Rust with extremely low overhead

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

py-spy

A sampling profiler for Python programs written in Rust that allows developers to visualize what their Python programs are spending time on without restarting the program or modifying code. py-spy operates outside the profiled Python process with extremely low overhead, making it safe for production use.

Package Information

  • Package Name: py-spy
  • Package Type: pypi
  • Language: Rust (command-line tool)
  • Installation: pip install py-spy
  • Platforms: Linux, macOS, Windows, FreeBSD
  • Python Support: 2.3-2.7, 3.3-3.13

Core Imports

py-spy is primarily used as a command-line tool installed via pip. For advanced users who want to embed py-spy functionality in Rust applications:

use py_spy::{Config, PythonSpy, StackTrace, Frame, Pid};
use py_spy::sampler::Sampler;
use anyhow::Error;

Basic Usage

Command Line Interface

# Profile existing process (record to flamegraph)
py-spy record -o profile.svg --pid 12345

# Profile new Python program
py-spy record -o profile.svg -- python myprogram.py

# Live console view (like top)
py-spy top --pid 12345

# Single stack trace snapshot
py-spy dump --pid 12345

Rust Library API

use py_spy::{Config, PythonSpy, Pid};
use anyhow::Error;

fn profile_python_process(pid: Pid) -> Result<(), Error> {
    // Create configuration with defaults
    let config = Config::default();
    
    // Create profiler instance
    let mut spy = PythonSpy::new(pid, &config)?;
    
    // Get current stack traces
    let traces = spy.get_stack_traces()?;
    
    // Process each thread's stack trace
    for trace in traces {
        println!("Thread {:#X} ({})", trace.thread_id, trace.status_str());
        for frame in &trace.frames {
            println!("  {} ({}:{})", frame.name, frame.filename, frame.line);
        }
    }
    
    Ok(())
}

Architecture

py-spy uses a multi-layered architecture for safe, cross-platform Python process profiling:

  • Process Memory Access: Platform-specific memory reading (process_vm_readv on Linux, vm_read on macOS, ReadProcessMemory on Windows)
  • Python Interpreter Analysis: Version-specific bindings for Python 2.3-3.13 to parse interpreter state
  • Stack Trace Collection: Traverses PyFrameObject chains to reconstruct call stacks
  • Native Extension Support: Optional libunwind integration for C/C++/Cython profiling
  • Output Generation: Multiple format support (flamegraph, speedscope, Chrome trace, raw data)

This design enables py-spy to profile Python processes safely without code modification or significant performance impact.

Capabilities

Command Line Interface

Complete command-line profiling tool with three main subcommands and extensive configuration options for production and development use.

py-spy record [OPTIONS] [--pid PID | -- PYTHON_PROGRAM...]
py-spy top [OPTIONS] [--pid PID | -- PYTHON_PROGRAM...]
py-spy dump [OPTIONS] [--pid PID | -- PYTHON_PROGRAM...]

Command Line Interface

Rust Library API

Programmatic profiling interface for integrating py-spy functionality into Rust applications and custom profiling tools.

struct PythonSpy;
impl PythonSpy {
    fn new(pid: Pid, config: &Config) -> Result<PythonSpy, Error>;
    fn get_stack_traces(&mut self) -> Result<Vec<StackTrace>, Error>;
}

struct Sampler;
impl Sampler {
    fn new(pid: Pid, config: &Config) -> Result<Sampler, Error>;
}
impl Iterator for Sampler {
    type Item = Sample;
}

Rust Library API

Configuration and Output Formats

Comprehensive configuration system supporting multiple profiling modes, output formats, and platform-specific options.

struct Config {
    blocking: LockingStrategy,
    native: bool,
    sampling_rate: u64,
    format: Option<FileFormat>,
    // ... additional fields
}

enum FileFormat {
    flamegraph,    // SVG flamegraph
    speedscope,    // JSON for speedscope.app
    chrometrace,   // Chrome trace format
    raw,          // Raw flamegraph data
}

Configuration and Output

Core Types

Stack Trace Representation

struct StackTrace {
    pid: Pid,
    thread_id: u64,
    thread_name: Option<String>,
    os_thread_id: Option<u64>,
    active: bool,
    owns_gil: bool,
    frames: Vec<Frame>,
    process_info: Option<Arc<ProcessInfo>>,
}

impl StackTrace {
    fn status_str(&self) -> &str;
    fn format_threadid(&self) -> String;
}

Frame Information

struct Frame {
    name: String,
    filename: String,
    module: Option<String>,
    short_filename: Option<String>,
    line: i32,
    locals: Option<Vec<LocalVariable>>,
    is_entry: bool,
    is_shim_entry: bool,
}

Process Identification

type Pid = remoteprocess::Pid;

Configuration Enums

enum LockingStrategy {
    Lock,         // Standard blocking mode
    NonBlocking,  // Minimal performance impact
    AlreadyLocked, // Process already locked
}

enum RecordDuration {
    Unlimited,
    Seconds(u64),
}

enum LineNo {
    NoLine,
    First,
    LastInstruction,
}
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/py-spy@0.4.x
Publish Source
CLI
Badge
tessl/pypi-py-spy badge