proctrace
Non-invasive process and OS state introspection for Python developers.
Diagnose memory leaks, file descriptor leaks, race conditions, and IPC bottlenecks with a single import — no agents, no profilers, no code changes required.
Built on a Rust core exposed to Python via PyO3 and Maturin.
Status: Under construction.
Platform support: Linux ✓ · macOS ✓ · Windows ✗
Python: ≥ 3.10
License: MIT
Installation
pip install proctrace
Or to build from source (requires Rust + maturin):
pip install maturin
maturin develop --release
Quick Start
Context manager
import proctrace
with proctrace.watch() as probe:
your_code_here()
print(probe.result.report())
Sample output:
┌─ proctrace ResourceDelta ──────────────────────────────────┐
│ memory rss +12.34 MB │
│ memory peak +45.00 MB │
│ virtual mem +8.00 MB │
│ open fds +3 │
│ threads +2 (new: worker-1, worker-2) │
│ child procs +0 │
│ elapsed 142.5 ms │
└────────────────────────────────────────────────────────────┘
Decorator
from proctrace.decorators import probe
@probe(memory=True, fds=True, output="stderr")
def load_data(path):
...
load_data("big_file.csv")
# ResourceDelta printed to stderr automatically
# Access the result programmatically
result = load_data.last_probe_result
print(result.rss_delta_mb)
Works on both regular and async functions.
API Reference
proctrace.watch(...) → ResourceWatcher
Returns a context manager that snapshots OS resources before and after the block.
| Parameter | Type | Default | Description |
|---|---|---|---|
memory |
bool |
True |
Track RSS / VMS memory |
fds |
bool |
True |
Track open file descriptors |
threads |
bool |
True |
Track thread count and names |
children |
bool |
True |
Track child process count |
sample_interval |
float |
0.1 |
Background sampler interval in seconds (for peak RSS) |
After the with block, probe.result is a ResourceDelta.
ResourceDelta
| Attribute | Type | Description |
|---|---|---|
rss_delta_bytes |
int |
RSS change in bytes (can be negative) |
vms_delta_bytes |
int |
Virtual memory size change |
fd_delta |
int |
Open FD count change |
peak_rss_bytes |
int |
Highest RSS seen during the block |
thread_delta |
int |
Thread count change |
child_delta |
int |
Child process count change |
elapsed_ns |
int |
Wall-clock time of block in nanoseconds |
leaked_fds |
list[str] |
FD paths present at exit but not at entry |
new_thread_names |
list[str] |
Names of threads created during the block |
Convenience properties: .rss_delta_mb, .vms_delta_mb, .peak_rss_mb, .elapsed_ms.
Serialization: .to_dict(), .to_json(indent=...), .from_dict(d).
@probe(...) decorator
from proctrace.decorators import probe
@probe(
memory=True,
fds=True,
threads=True,
children=False,
sample_interval=0.05,
output="stderr", # or "none"
store=True, # stores result on fn.last_probe_result
)
def my_function(): ...
IPC Tracing
Wrap queues, pipes, and sockets to measure latency and throughput:
import queue, os
from proctrace.ipc import trace_ipc, trace_pipe, trace_socket, ipc_report
# Queues
q = trace_ipc(queue.Queue(), name="task-queue")
q.put(item)
item = q.get()
# OS pipes
r_fd, w_fd = os.pipe()
pipe = trace_pipe(r_fd, w_fd, name="my-pipe")
pipe.write(b"hello")
data = pipe.read(5)
# Sockets
sock = trace_socket(raw_socket, name="worker-conn")
sock.sendall(b"data")
response = sock.recv(1024)
# Print a report of all traced channels
print(ipc_report())
On-demand stack dumps
Install a signal handler to dump all threads and asyncio tasks to stderr on demand:
import proctrace
proctrace.install_signal_handler(sig="SIGUSR1") # SIGUSR1, SIGUSR2, or SIGALRM
# From the terminal:
# kill -USR1 <pid>
Outputs a timestamped dump of every thread's stack trace plus any running asyncio tasks.
CLI
proctrace <subcommand> [options]
proctrace run — measure a subprocess
proctrace run -- python myscript.py
proctrace run --json -- python myscript.py # JSON output to stdout
proctrace watch — live memory polling
proctrace watch --pid <PID> --interval 1.0 --duration 30
Prints a live-updating table of RSS and VMS (MB) for the target process.
proctrace dump — trigger a stack dump
proctrace dump --pid <PID> --signal SIGUSR1
Sends a signal to a running proctrace-instrumented process to trigger a thread dump.
Benchmarks
Measured on a quiet machine: single-threaded hot loop, 200,000 iterations of
snapshot_resources(), which reads memory, FD count, and thread state in a
single Rust call.
Snapshot latency
| Operation | Latency | Throughput |
|---|---|---|
snapshot_resources() |
7.9 µs/call | ~127k calls/s |
Detection accuracy
Scenario: inside the measured region, allocate 64 MB, open 10 FDs, start 2 threads, and spawn 1 child process.
| Metric | Detected |
|---|---|
| RSS delta | +64.3 MB |
| Open FD delta | +10 |
| Thread delta | +2 |
| Child process delta | +1 |
Measured on: Linux 7.1.8 (x86_64, 12 cores), CPython 3.14, proctrace 0.1.0. Results vary by machine.
Development
# Create virtual environment
python -m venv .venv && source .venv/bin/activate
# Install dev dependencies and build the Rust extension
pip install -e ".[dev]"
maturin develop
# Run tests
pytest
Requires: Rust toolchain, Python ≥ 3.10.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file proctrace-0.1.0.tar.gz.
File metadata
- Download URL: proctrace-0.1.0.tar.gz
- Upload date:
- Size: 67.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0879c09ffcc3946547aa50147012aa15f37d371f00022aa842b771ab19413b66
|
|
| MD5 |
8e3b41d30d799529693fda179272d690
|
|
| BLAKE2b-256 |
0dd6957a0dea4fa536e4f2d1fa72a444e2bddb1a1d35d037d9f1b9e901307981
|
File details
Details for the file proctrace-0.1.0-cp314-cp314-manylinux_2_34_x86_64.whl.
File metadata
- Download URL: proctrace-0.1.0-cp314-cp314-manylinux_2_34_x86_64.whl
- Upload date:
- Size: 267.2 kB
- Tags: CPython 3.14, manylinux: glibc 2.34+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3f61d8ebf4f59e894a8fef8e8d89febfd36ad7a512bd682729745f7a64fc85e4
|
|
| MD5 |
3410e1ab2ebdee77a286d5c1a617958a
|
|
| BLAKE2b-256 |
bfda2eda52d6139c50c4706b1baae06415a6ab50582769fcb71d0362693b243e
|