py-spy dump: Snapshot Python Thread Stacks
py-spy dump prints a one-shot snapshot of every thread stack in a running Python process, without stopping it for long.
When a Python job hangs in CI, py-spy dump answers "where is it stuck" instantly by showing every thread stack, no debugger attach or signal handler needed.
What it does
py-spy dump reads a running Python process once and prints the current call stack of each thread, including the file, line, and function at every frame. It is the fastest way to see where a hung or deadlocked process is blocked.
Common usage
py-spy dump --pid 12345
# include local variables in the dump
py-spy dump --pid 12345 --localsOptions
| Flag | What it does |
|---|---|
| --pid <pid> | The Python process to snapshot (required) |
| -l / --locals | Also print local variables in each frame |
| --native | Include native C frames |
In CI
A useful pattern: when a Python step exceeds a soft timeout, run py-spy dump --pid on it before killing the job, so the logs capture exactly where it hung. This needs ptrace access, so add SYS_PTRACE in containers.
Common errors in CI
"Permission denied" / "Operation not permitted (os error 1)" is the ptrace block; grant SYS_PTRACE or relax ptrace_scope. "No such process" means the pid already exited. If frames read "<unknown>", the interpreter build lacks the symbols py-spy expects, common with heavily stripped or unusual CPython builds.