Skip to content

Guide · Open source

How to use py-spy: profile a running Python program

Updated · written with AI from the project's own documentation and checked against our catalogue data

py-spy is a sampling profiler for Python programs. It shows which functions your program spends time in, and it does this from outside the program, so you do not need to restart the program or add profiling code to it. This guide covers installing py-spy, the three commands it offers (record, top and dump), and the permission issues you may hit on Linux. After reading it, you will be able to profile a Python process and get a single call-stack dump from a stuck one.

py-spybenfred/py-spy · ★ 15.6k · MIT

Quick start

  1. 1Install py-spy. Run pip install py-spy, or brew install py-spy on macOS.
  2. 2Find the process ID. Get the PID of the running Python program you want to sample.
  3. 3Record a flame graph. Run py-spy record with -o set to an SVG file name and --pid set to your PID, then open the SVG in a browser.
  4. 4Check live activity. Run py-spy top --pid with your PID to see which functions take the most time right now.
  5. 5Dump a stuck process. Run py-spy dump --pid with your PID to see each thread's current call stack, adding --locals if you need variable values.
  6. 6Handle permissions. If attaching fails on Linux, retry with sudo, or start the program through py-spy so it runs as a child process.

Install py-spy

The simplest route is to install the prebuilt binary wheel from PyPI. On macOS you can use Homebrew instead.

py-spy is also available as a prebuilt binary on the GitHub Releases page. If you are a Rust user, it can be installed with cargo, which builds from source and requires libunwind on Linux and Windows. The README also lists packages for Arch Linux (AUR) and Alpine Linux (testing repository).

  • PyPI: use the pip command below
  • macOS: use the Homebrew command below
  • Other options: GitHub Releases binaries, cargo, AUR, or the Alpine testing repository
pip install py-spy # macOS brew install py-spy

Understand the three commands

py-spy takes either the PID of a running Python program or the command line of a program it should start. It has three subcommands: record, top and dump.

  • record: writes a profile to a file, such as a flame graph SVG, speedscope profile or raw data
  • top: shows a live, top-style view of the functions taking the most time
  • dump: prints the current call stack for each Python thread

Record a flame graph

Use record to generate a flame graph of a Python process. You can attach to a running process by PID, or have py-spy launch the program for you. The output is an interactive SVG file.

Use the --format parameter to produce speedscope profiles or raw data instead. Run py-spy record --help to see other options, including the sampling rate, filtering to threads that hold the GIL, profiling native C extensions, showing thread IDs and profiling subprocesses.

py-spy record -o profile.svg --pid 12345 # OR py-spy record -o profile.svg -- python myprogram.py

Watch live performance with top

The top view works like the Unix top command. It shows a live, updating summary of which functions take the most time in your program. You can start it with a PID or with a program command line.

py-spy top --pid 12345 # OR py-spy top -- python myprogram.py

Dump call stacks from a hung process

When you only need a single snapshot, use dump. It prints the call stack for each Python thread along with some basic process information. This is useful when you want to see where a program is stuck.

Add the --locals flag to also print the local variables for each stack frame.

py-spy dump --pid 12345

Fix permission errors on Linux

py-spy reads memory from another Python process, and your operating system may block this. On OSX it always requires root. On Linux, the default setting requires root when attaching to a process that py-spy did not create.

You can avoid sudo on Linux by letting py-spy start the program. Attaching to an existing PID usually needs root. The README notes that you can remove this restriction by changing the ptrace_scope sysctl setting, though that is a system-wide security change.

  • Works without root: py-spy record -- python myprogram.py
  • Usually needs root: sudo py-spy record --pid 123456
sudo py-spy record --pid 123456

What people use it for

  • Finding which functions make a slow Python script take most of its time, using a flame graph
  • Checking a live service with top-style output without restarting it
  • Finding where a hung process is blocked by dumping its call stacks
  • Profiling gunicorn worker pools or multiprocessing programs with the --subprocesses flag

Frequently asked questions

Is py-spy free to use?

py-spy is released under the MIT licence, and its source is on GitHub. The README does not describe any paid tier, so you can use it as an open-source tool.

Which platforms does py-spy support?

The README says py-spy works on Linux, OSX, Windows and FreeBSD. It supports recent CPython versions, and the README lists the exact range of supported interpreter versions.

Do I need to change my code to use py-spy?

No. py-spy runs as a separate process and reads the target program's memory, so you do not need to restart the program or add profiling code. The README says it is safe to use against production code.

Why does py-spy need sudo on Linux?

Linux blocks reading memory from other processes by default when they were not started by the tool. Running as root or starting the program through py-spy avoids this, and the README explains the ptrace_scope setting if you want to change the system default.

Can py-spy profile C extensions?

Yes, on some platforms. Pass --native to record, and compile the extension with symbols for best results. The README includes a platform support table that shows where this works.

How does py-spy compare to cProfile or pyinstrument?

py-spy is a sampling profiler that runs outside the program and needs no code changes. cProfile, Scalene, Austin and pyinstrument are other Python profilers in the same space, and the README does not compare them directly. Choose based on whether you need to avoid touching code or need exact call counts, which py-spy does not provide.

New agent skills, repos and AI tools — every week

The best new skills and open-source projects, the fastest-growing repos, and one free prompt. Five minutes to read. Unsubscribe anytime.

Our verdict

py-spy suits developers and engineers who need to profile slow Python code, inspect hung processes, or check production services without restarting them or changing code. If you need exact call counts or deterministic tracing, or you cannot run as root when attaching on Linux, pick a different tool such as cProfile.

Install options & downloads