explaingit

benfred/py-spy

Analysis updated 2026-06-24

15,178RustAudience · developerComplexity · 2/5LicenseSetup · easy

TLDR

py-spy is a sampling profiler that watches a running Python process from the outside and reports where time is spent, without code changes or restarts.

Mindmap

mindmap
  root((py-spy))
    Inputs
      Running Python PID
      CPython 2.3 to 3.14
    Outputs
      Flame graph SVG
      Live top view
      Stack dumps
    Use Cases
      Profile production app
      Debug a hung process
      Find hot functions
    Tech Stack
      Rust
      CPython
      Linux
      macOS
Click or tap to explore — scroll the page freely

Code map

Detail Auto

An interactive map of this repo's files and how they connect — its source is parsed live in your browser. Click Visualize to build it.

filefunction / class

What do people build with it?

USE CASE 1

Profile a live production Python service without restarting it or editing its code.

USE CASE 2

Watch a top-style terminal view of the hottest Python functions in a running app.

USE CASE 3

Dump the call stack of every thread to diagnose a hung Python process.

USE CASE 4

Record a flame graph that includes native C, C++, and Cython extension frames.

What is it built with?

RustPythonCPython

How does it compare?

benfred/py-spyquickwit-oss/tantivycanner/wrenai
Stars15,17815,18015,194
LanguageRustRustRust
Setup difficultyeasymoderatemoderate
Complexity2/54/54/5
Audiencedeveloperdeveloperdata

Figures from each repo's GitHub metadata at analysis time.

How do you get it running?

Difficulty · easy Time to first run · 5min

Reading another process's memory often needs root on Linux and always on macOS.

MIT licensed: use freely in personal and commercial projects as long as the copyright notice is kept.

In plain English

py-spy is a tool that watches a running Python program from the outside and reports which parts of its code are taking the most time. The category it belongs to is called a sampling profiler. Sampling profilers periodically check what a program is doing, then aggregate those snapshots to show where time is spent. The distinguishing point of py-spy is that you do not need to restart the Python program or change a single line of its source code to use it. You just point py-spy at the running process. The README emphasises that py-spy is safe to use on production code. It is written in Rust, which the author cites for speed, and it runs in a separate process from the Python program it is watching. A buggy or slow profiler cannot interfere with the program serving real traffic because the profiler is not inside it. py-spy works on Linux, macOS, Windows, and FreeBSD, and supports CPython versions 2.3 through 2.7 and 3.3 through 3.14. Installation is usually one command, such as pip install py-spy or brew install py-spy on macOS. py-spy has three subcommands. record writes a profile to a file, by default an interactive SVG flame graph that shows which function calls dominated, with options for speedscope-format output or raw data. top shows a live updating view in the terminal of the functions currently using the most time, modelled on the Unix top command. dump prints the current call stack for every Python thread once, which the README describes as useful when you need to find where a hung program is stuck. A --locals flag also prints the local variables in each stack frame. Under the hood, py-spy reads the memory of the target Python process directly, using process_vm_readv on Linux, vm_read on macOS, and ReadProcessMemory on Windows. It walks the Python interpreter's internal data structures to reconstruct the call stack of each Python thread. Because Python's internal layout changes between versions, py-spy uses Rust's bindgen tool to generate per-version definitions of the relevant structures. When the target Python binary is stripped of symbols, py-spy scans memory for something that looks like a valid interpreter state. Other documented features include profiling native C, C++, or Cython extensions with --native, profiling all child processes with --subprocesses, and a note that reading another process's memory often requires running as root on Linux and always requires it on macOS.

Copy-paste prompts

Prompt 1
Show me how to attach py-spy to a running gunicorn worker and record a flame graph SVG for 30 seconds.
Prompt 2
Use py-spy top to watch the live hot functions of a Django process by PID and explain the columns.
Prompt 3
Run py-spy dump --locals on a hung Python process and walk me through reading the output.
Prompt 4
Profile a multiprocessing pool with py-spy --subprocesses and aggregate the result into one speedscope file.
Prompt 5
Set up py-spy in a Docker container with the right capabilities so it can read the target process memory without sudo.

Frequently asked questions

What is py-spy?

py-spy is a sampling profiler that watches a running Python process from the outside and reports where time is spent, without code changes or restarts.

What language is py-spy written in?

Mainly Rust. The stack also includes Rust, Python, CPython.

What license does py-spy use?

MIT licensed: use freely in personal and commercial projects as long as the copyright notice is kept.

How hard is py-spy to set up?

Setup difficulty is rated easy, with roughly 5min to a first successful run.

Who is py-spy for?

Mainly developer.

Open on GitHub → Explain another repo

This repo across BitVibe Labs

Verify against the repo before relying on details.