English | 简体中文 | 日本語 | 한국어 | Tiếng Việt | Français | Deutsch
sgrud (from Scottish Gaelic sgrùd, meaning "inspection" or "examination") is a diagnostic tool for inspecting running Python processes. Attach to a CPython process and watch its memory, CPU, threads, asyncio tasks, stacks and garbage collector without slowing it down.
sgrud never stops or instruments the target. It reads interpreter state straight out of process memory through CPython 3.15's _remote_debugging module (the machinery behind the Tachyon profiler and python -m asyncio ps) and pairs it with what the OS reports through psutil for memory, CPU, threads and open files. A snapshot of every thread's stack costs tens of microseconds and nothing on the target side.
A tour of the tabs with examples/demo_app.py as the target: threads, asyncio tasks, GC, child processes, hotspots, the flame graph and IPC.
- Process: memory broken down as far as the platform allows, CPU, page faults, limits, the cgroup's quota and throttling, and the child processes with the Python interpreters among them marked. Select a Python child and press Enter to inspect it, then
bto return. - Threads: every thread with its state, CPU share, live Python stack and, on Linux, the system call it is blocked in.
- Tasks: the asyncio task tree, each task with the coroutine frames it is parked in.
- GC: time spent collecting, collection rate, tracked objects, a history of collections and the functions that triggered them.
- Hotspots and Flame: a background sampling profiler with CPU, wall, GIL, exception and asyncio task modes, shown as a table or a flame graph, cumulatively or over the last 30 seconds / 5 minutes.
- IPC: open descriptors, pipes and who holds their other ends, sockets, shared memory and file locks, for the process that hangs.
sgrud dumpprints the same as text or JSON,sgrud profilesamples for a while and writes any Tachyon format, andsgrud probeasks the target for what memory alone cannot show.--webserves the interface to a browser.- A
Monitorclass that returns plain dataclasses, so all of it is available as a library.
pip install sgrud
pip install "sgrud[web]" # adds --web
uv tool install sgrud and pipx install sgrud work too. sgrud needs CPython 3.15 or newer on Linux, macOS or Windows, and the target must run the same major.minor version as sgrud itself.
Memory, CPU and thread names work for any process you own. Reading the interpreter's state needs ptrace rights on Linux, root on macOS and the same user on Windows. Without them sgrud attaches in limited mode and says what is missing. The simplest way to get everything is to start the target through sgrud, see Permissions for the other ways.
sgrud PID interactive terminal interface
sgrud run -- python app.py start the target as a child and inspect it
sgrud PID --web the same interface served to a browser
sgrud dump PID one text snapshot, --json for JSON
sgrud profile PID -d 30 --mode gil sample the GIL holder for 30 s, print the hottest functions
sgrud profile PID -o out.html write a flame graph instead
sgrud probe PID run a script inside the target: gc thresholds, allocator, threads
examples/demo_app.py puts something on every tab. Start it and point sgrud at the pid it prints.
From Python:
from sgrud import Monitor
with Monitor.attach(pid) as m: # or Monitor.spawn(["python", "app.py"])
snap = m.snapshot()
print(snap.process.memory.rss, snap.process.cpu_percent)
for t in snap.threads:
print(t.tid, t.name, t.status.describe(), t.frames[:1])The reference covers every command and option, the sampling modes and output formats, the TUI's keys and tabs, the library, what each platform reports and how to get the permissions.
uv sync
uv run pytest
The tests spawn tests/target_app.py and inspect it, so they exercise the real attach path. The Textual app is tested headlessly through its pilot.