Registry / observability / py-spy

py-spy

JSON →
library0.4.1pypypiunverified

py-spy is a sampling profiler for Python programs, implemented in Rust, designed for extremely low overhead. It enables visualization of Python program execution without requiring restarts or code modification, making it safe for production environments. The library actively maintains support across Linux, macOS, Windows, and FreeBSD, covering a wide range of CPython interpreter versions, with a continuous release cadence reflected by recent minor version updates.

pip install py-spy
INSTALL
IMPORT
SIG · PY-SPY
P
py-spy
observabilitypythonv0.4.1
harness data pending
Install & Compatibility
Where this runs

No compatibility data collected yet for this library.

Code
Verified usage

This quickstart demonstrates how to use `py-spy` to record a flame graph (`profile.svg`) of a running Python process. It first starts a simple Python script in the background, then attaches `py-spy` to its process ID (PID) to capture profiling data. For live viewing, `py-spy top --pid <PID>` is also a common command. Remember that `py-spy` often requires elevated privileges (e.g., `sudo`) or specific system capabilities (like `SYS_PTRACE` in Docker) to function correctly when attaching to existing processes.

import time import subprocess import os # Create a dummy Python script to profile python_script_content = """ import time import sys def busy_loop(iterations): result = 0 for i in range(iterations): result += i * i return result def main(): print(f"[{os.getpid()}] Starting my_app.py...") for _ in range(5): busy_loop(1_000_000) time.sleep(0.5) print(f"[{os.getpid()}] my_app.py finished.") if __name__ == "__main__": main() """ with open("my_app.py", "w") as f: f.write(python_script_content) print("Running my_app.py in the background...") # Start the target Python script in the background # In a real scenario, you'd profile an already running process by PID # For quickstart, we launch it and then 'profile' it (though py-spy can launch directly too) process = subprocess.Popen([sys.executable, "my_app.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) pid = process.pid print(f"Target Python process PID: {pid}") # Wait a bit for the script to start time.sleep(2) print("Recording profile with py-spy...") # Example: Record a flame graph of the running process # On Linux, you might need 'sudo' if attaching to an existing process (not a child) # On Docker, ensure --cap-add SYS_PTRACE is used # os.environ.get is not directly applicable here as py-spy is a CLI tool # but the principle for quickstarts is to show a runnable example. try: # Using subprocess.run for simplicity, would typically be a direct shell command # For this example, we assume necessary permissions are available (e.g., running as root or correct ptrace_scope) # In a real shell, you'd do: py-spy record -o profile.svg --pid <PID> result = subprocess.run(["py-spy", "record", "-o", "profile.svg", "--pid", str(pid)], capture_output=True, text=True, check=True) print("py-spy stdout:", result.stdout) print("py-spy stderr:", result.stderr) print("Flame graph saved to profile.svg") except subprocess.CalledProcessError as e: print(f"Error running py-spy: {e}") print("py-spy stdout:", e.stdout) print("py-spy stderr:", e.stderr) print("HINT: You might need to run this with 'sudo' or ensure appropriate ptrace permissions.") except FileNotFoundError: print("Error: py-spy command not found. Ensure py-spy is installed and in your PATH.") finally: # Clean up the background process if process.poll() is None: process.terminate() process.wait(timeout=5) # Clean up the dummy script os.remove("my_app.py") if os.path.exists("profile.svg"): print("To view the profile, open profile.svg in a web browser.")
py-spy --version
Debug
Known issues
breakingpy-spy frequently requires elevated permissions to profile running processes. On Linux, attaching to an existing process usually necessitates `sudo` or modification of `ptrace_scope`. For Docker or Kubernetes containers, the container must be launched with `--cap-add SYS_PTRACE` to allow `py-spy` to read process memory. On macOS, running `py-spy` as root (`sudo`) is generally required.
fix
Run `py-spy` with `sudo` when attaching to existing processes. For Docker, add `--cap-add SYS_PTRACE` to your `docker run` or `docker-compose.yml` configuration. Ensure `ptrace_scope` is configured appropriately on Linux if `sudo` is not desired.
affects: All versions
gotchaOlder versions of `py-spy` might not fully support profiling newer Python interpreters due to changes in CPython's internal ABI. For example, Python 3.12 and 3.13 support was added in recent `py-spy` releases (v0.4.0+), and using older `py-spy` versions with these Python versions could lead to errors or inaccurate profiling.
fix
Always use the latest available `py-spy` version to ensure compatibility with the Python interpreter you are profiling. `pip install --upgrade py-spy`.
affects: < 0.4.0
gotchaOn macOS, System Integrity Protection (SIP) prevents `py-spy` from profiling Python interpreters installed at `/usr/bin`. Attempting to profile such interpreters will fail.
fix
Profile Python interpreters installed via alternative methods (e.g., Homebrew, Anaconda, pyenv) or within an active virtual environment, as these are typically located outside `/usr/bin`.
affects: All versions on macOS
gotchaProfiling very idle Python programs or those with highly regular, periodic activity can result in misleading or inaccurate flame graphs and `top` output due to sampling aliasing. `py-spy`'s default sampling rate might coincidentally align with program's internal ticks, leading to over- or under-reporting of activity.
fix
Use the `--idle` flag to include idle frames in the profile, or the `--nonblocking` option to avoid pausing the target (though this may introduce occasional sampling errors). Consider adjusting the sampling rate (`-r` option) to a non-standard value to mitigate aliasing, although it might not fully eliminate the issue.
affects: All versions
gotchapy-spy is a CPU sampling profiler only and does not provide functionality for memory profiling. It cannot diagnose memory leaks, track memory allocation/deallocation, or optimize memory usage.
fix
For memory analysis, use dedicated Python memory profiling tools (e.g., `memory_profiler`, `objgraph`, built-in `tracemalloc`) in conjunction with `py-spy` for a comprehensive performance overview.
affects: All versions
breakingThe `py-spy` tool relies on a correctly executing Python environment and launch script. If the script attempting to run `py-spy` or the application being profiled contains fundamental Python errors (e.g., `NameError` for an unimported module), `py-spy` may not be able to execute or attach successfully.
fix
Ensure the script launching `py-spy` or the target application is syntactically correct and all necessary modules are imported (e.g., `import sys` if using `sys.executable`). Verify the Python environment is stable and correctly configured.
affects: All versions
breakingInstallation of `py-spy` on Alpine Linux (or other musl-libc based systems) fails if essential build dependencies, including `gcc` and its runtime libraries, are not present. The Rust toolchain, which `py-spy` compiles with, expects these libraries, and their absence results in 'Error loading shared library libgcc_s.so.1' or similar linking errors during the `cargo` execution phase.
fix
Prior to installing `py-spy` on Alpine Linux, install the necessary build tools and libraries using `apk add build-base gcc musl-dev libgcc`. For other musl-libc based systems, identify and install their respective `gcc` and `libgcc` packages.
affects: All versions on Alpine Linux or musl-libc based systems
Errors
Common errors & fixes
Permission Denied: Try running again with elevated permissions by going 'sudo env "PATH=$PATH" !!'
py-spy needs elevated permissions to read memory from other processes, which is often restricted by the operating system (Linux, macOS) or container environments (Docker, Kubernetes) for security reasons.
fix
Run py-spy with `sudo`. For Docker, start the container with `--cap-add SYS_PTRACE`. For Kubernetes, add `SYS_PTRACE` capability to the container's security context.
Error: Failed to find a python interpreter in the .data section
py-spy struggles to locate the Python interpreter's internal structures (like `_PyRuntime` or version info) within the target process's memory. This is common on Windows, with Python versions 3.10 and newer, or when Python debug symbols are not installed.
fix
On Windows, ensure Python was installed with 'Debug Symbols' and 'Debug Binaries'. Consider using a Python version where this is less common (e.g., Python < 3.10 if available and compatible). Upgrading py-spy to the latest version might also resolve compatibility issues with newer Python interpreters.
Error: No such file or directory (os error 2)
This error typically occurs when py-spy cannot find the executable of the profiled Python process. This can happen if the process with the given PID no longer exists, if the path to the Python executable is reported incorrectly (e.g., when the executable has been deleted/upgraded), or when profiling a Docker container from the host where the path inside the container is not visible to the host.
fix
Verify that the PID corresponds to a currently running Python process. If profiling a Docker container, either run `py-spy` inside the container or ensure the host can properly resolve the container's process paths, often by using `docker exec` to run `py-spy` within the container itself.
ERROR: Could not find a version that satisfies the requirement py-spy (from versions: none) ERROR: No matching distribution found for py-spy
This installation error indicates that `pip` could not find a pre-built wheel (binary distribution) for py-spy that matches your Python version, operating system, and architecture (e.g., 32-bit Python on a 64-bit OS, or specific Linux distributions like Alpine Linux which require special handling).
fix
Ensure you are using a 64-bit Python installation. If on Alpine Linux, you might need to add `echo 'manylinux1_compatible = True' > /usr/local/lib/pythonX.Y/site-packages/_manylinux.py` before `pip install py-spy` or install from the Alpine testing repository. Alternatively, download a prebuilt binary from the py-spy GitHub releases page.
Upgrade
Version history
0.4.1latest on PyPI · released Jul 31, 2025
Audit
Dependencies
Operating System ptrace capabilitiesrequiredpy-spy relies on OS-level system calls (e.g., `process_vm_readv` on Linux, `vm_read` on macOS, `ReadProcessMemory` on Windows) to read memory from the profiled Python process. The `SYS_PTRACE` capability is crucial on Linux for attaching to processes, especially in containerized environments.
Agent activity
61 hits · last 30 days
node
56
OpenAI (training)
2
Resources
py-spy — pip install py-spy · libregistry