Skip to main content

A Python dynamic debugger inspired by Arthas, using Python 3.14's safe external debugger interface

Project description

  Peeka

PyPI Release Tests License

中文 | English

Roadmap: English | 中文

Peek-a-boo! — The name comes from the children's game. A diagnostic tool finding a hidden bug feels just like that moment of surprise when someone is found in hide-and-seek.

Runtime diagnostic tool for Python applications, inspired by Alibaba Arthas. Non-invasive function observation with zero code changes.

Uses PEP 768 (sys.remote_exec) on Python 3.14+, with debugger-based fallback for Python 3.8–3.13 (GDB on Linux, LLDB on macOS).

Key Features

  • Non-invasive — Inject observation logic at runtime, fully restored on detach
  • Real-time streaming — Millisecond-latency data via Unix domain sockets
  • Production-safe — < 5% overhead, fixed-size memory buffers, graceful error recovery
  • Secure filteringsimpleeval-based condition expressions, blocks all code injection
  • Dual interface — CLI (JSONL output, pipe-friendly) and interactive TUI

Quick Start

Install

pip install peeka          # CLI only (Python 3.8+)
pip install peeka[tui]     # CLI + TUI (Python 3.9+)

Basic Usage

# 1. Attach to a running Python process
peeka-cli attach <pid>

# 2. Watch function calls
peeka-cli watch "module.Class.method" -n 5

# 3. Watch with condition filter
peeka-cli watch "module.func" --condition "params[0] > 100"

# 4. Trace call tree with timing
peeka-cli trace "module.func" -d 3

# 5. Capture call stack
peeka-cli stack "module.func" -n 3

# 6. Launch TUI
peeka

Pipe-Friendly Output (JSONL)

All CLI output is JSONL — one JSON object per line with a type field:

# Filter observations with jq
peeka-cli watch "module.func" | jq 'select(.type == "observation")'

# Find slow calls
peeka-cli watch "module.func" | jq 'select(.type == "observation" and .data.duration_ms > 100)'

# Save to file
peeka-cli watch "module.func" > observations.jsonl

Commands

Command Description
attach Attach to a running Python process
watch Observe function calls (args, return, time)
trace Trace call tree with timing breakdown
stack Capture call stack at function entry
monitor Periodic performance statistics
logger Adjust log levels at runtime
memory Memory usage analysis
inspect Runtime object inspection
sc/sm Search classes / search methods
thread Thread analysis and diagnostics
top Function-level performance sampling
reset Remove all injected enhancements
detach Detach from target process
run Run a script with Peeka injected from startup

watch

peeka-cli watch <pattern> [options]
Option Description Default
-x, --depth Output depth for nested objects 2
-n, --times Number of observations (-1 = infinite) -1
--condition Filter expression (e.g. params[0] > 100, cost > 50)
-b, --before Observe at function entry false
-s, --success Observe on success only false
-e, --exception Observe on exception only false
-f, --finish Observe on finish (success or exception) true

Pattern format: module.Class.method or module.function

trace

peeka-cli trace <pattern> [options]
Option Description Default
-d, --depth Max call tree depth 3
-n, --times Number of observations (-1 = infinite) -1
--condition Filter expression (e.g. cost > 50)
--skip-builtin Skip stdlib/built-in functions true
--min-duration Minimum duration filter (ms) 0

Output example:

`---[125.3ms] calculator.Calculator.calculate()
    +---[2.1ms] calculator.Calculator._validate()
    +---[98.2ms] calculator.Calculator._compute()
    |   `---[95.1ms] math.sqrt()
    `---[15.7ms] calculator.Logger.info()

stack

peeka-cli stack <pattern> [options]
Option Description Default
-n, --times Number of captures (-1 = infinite) -1
--condition Filter expression
--depth Stack depth limit 10

reset

peeka-cli reset [pattern] [options]
Option Description Default
-l, --list List current enhancements without reset false
pattern Optional glob pattern to filter targets
peeka-cli reset                    # Reset all enhancements
peeka-cli reset "mymodule.*"       # Reset matching functions only
peeka-cli reset --list             # List active enhancements

run

Run a Python script with Peeka injected from startup — useful when you need to observe code that runs at import time or in short-lived scripts.

peeka-cli run <script> [script_args] -- <command> [command_options]
peeka-cli run myscript.py -- watch "mymodule.func"
peeka-cli run myscript.py arg1 arg2 -- trace "mymodule.func" -d 3
peeka-cli run myscript.py -- watch "mymodule.func" --output-file out.jsonl
Option Description Default
--output-file Write JSONL output to file instead of stdout

Condition Expressions

Powered by simpleeval for safe evaluation:

params[0] > 100              # Positional argument check
len(params) > 2              # Argument count
kwargs.get('debug') == True  # Keyword argument check
cost > 50                    # Execution time in ms (watch/trace only)
str(x).startswith('prefix')  # String operations
x + y > 10                   # Arithmetic

Available variables: params (positional args list), kwargs (keyword args dict), result (return value, finish only), cost (duration ms, watch/trace only).

Security: Only safe operations (comparisons, arithmetic, logic) are allowed. eval, exec, __import__, open, compile and reflection via __class__/__subclasses__ are all blocked.

Output Format

Every line is a JSON object with a type field:

Type Description Commands
status Progress/info messages attach
success Command completed successfully attach, detach
error Command failed all
event Control events (started/stopped) watch, stack, monitor
observation Real-time observation data watch, stack, monitor
result Query results (non-streaming) logger, memory, sc, sm
Output examples
{"type": "status", "level": "info", "message": "Attaching to process 12345"}
{"type": "success", "command": "attach", "data": {"pid": 12345, "socket": "/tmp/peeka_xxx.sock"}}
{"type": "event", "event": "watch_started", "data": {"watch_id": "watch_001", "pattern": "module.func"}}
{
  "type": "observation",
  "watch_id": "watch_001",
  "timestamp": 1705586200.123,
  "func_name": "demo.Calculator.add",
  "args": [1, 2],
  "kwargs": {},
  "result": 3,
  "success": true,
  "duration_ms": 0.123,
  "count": 1
}
{"type": "error", "command": "watch", "error": "Cannot find target: invalid.pattern"}

Python Version Support

Python Version CLI TUI Attach Mechanism Requirements
3.14+ PEP 768 sys.remote_exec() Same UID or CAP_SYS_PTRACE
3.9–3.13 GDB (Linux) / LLDB (macOS) Linux: GDB 7.3+, ptrace ≤ 1
macOS: Xcode Command Line Tools
3.8 GDB (Linux) / LLDB (macOS) Linux: GDB 7.3+, ptrace ≤ 1
macOS: Xcode Command Line Tools

TUI requires Textual which needs Python ≥ 3.9.

Python < 3.14 Setup

Linux

GDB is required. Debug symbols are strongly recommended — some distros include them by default, but if GDB reports "no symbol" errors, install them:

# Debian/Ubuntu
sudo apt-get install gdb python3-dbg

# RHEL/Fedora
sudo yum install gdb python3-debuginfo

# Arch
sudo pacman -S gdb

macOS

LLDB is used instead of GDB. Install Xcode Command Line Tools if not already installed:

xcode-select --install

LLDB is included by default. No additional debug symbols are required.

Docker

docker run --cap-add=SYS_PTRACE your-image

ptrace Restrictions (Linux)

# Check current setting
cat /proc/sys/kernel/yama/ptrace_scope

# Temporarily allow (for testing)
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope

# SELinux (Fedora/RHEL)
sudo setsebool -P deny_ptrace=off

Note: macOS does not have ptrace_scope restrictions. System Integrity Protection (SIP) may prevent debugging some system processes, but user processes can be debugged normally.

Troubleshooting

Attach fails (permission denied)

  • Ensure same UID or CAP_SYS_PTRACE
  • Linux: Check ptrace_scope (see above)
  • Linux: Install debug symbols if GDB reports "no symbol" errors
  • macOS: Ensure Xcode Command Line Tools are installed (xcode-select --install)

No observation data

  • Verify function name (use fully qualified name: module.Class.method)
  • Confirm the function is actually being called
  • Check if condition expression is too restrictive

Target process behaving abnormally

# Remove observation on specific function
peeka-cli reset "module.func"

# Remove all injected enhancements
peeka-cli reset

# If issues persist, detach and restart target process
peeka-cli detach <pid>

Architecture

CLI/TUI  →  AgentClient  →  Unix Socket  →  PeekaAgent (injected in target)
                                              ├─ _register_handlers() → BaseCommand subclasses
                                              ├─ DecoratorInjector (function wrapping)
                                              └─ ObservationManager (buffered streaming)
  • Attach: PEP 768 sys.remote_exec() on 3.14+, GDB (Linux) or LLDB (macOS) on 3.8–3.13
  • Observe: Decorator injection wraps target functions, captures args/return/exceptions/timing
  • Stream: Real-time observation data via Unix domain socket (length-prefixed JSON)
  • Commands: Modular BaseCommand subclasses, registered in PeekaAgent._register_handlers()

License

Apache License 2.0

Acknowledgments

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

peeka-0.1.10.tar.gz (136.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

peeka-0.1.10-cp312-cp312-manylinux_2_34_x86_64.whl (180.2 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.34+ x86-64

File details

Details for the file peeka-0.1.10.tar.gz.

File metadata

  • Download URL: peeka-0.1.10.tar.gz
  • Upload date:
  • Size: 136.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for peeka-0.1.10.tar.gz
Algorithm Hash digest
SHA256 380a3d8b6c342f78efadb9c084094a4d6b5cc61c4e4174597a0f8f06574b70cf
MD5 49ef1593fa6592b7738816b50b5cb1f7
BLAKE2b-256 b7f93dfd806e23820f8d3efbdd73430c61fd27c975bfaf93bb021b1199c5d0d9

See more details on using hashes here.

Provenance

The following attestation bundles were made for peeka-0.1.10.tar.gz:

Publisher: publish-pypi.yml on wwulfric/peeka

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file peeka-0.1.10-cp312-cp312-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for peeka-0.1.10-cp312-cp312-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 517d1e080967fc415b1abb9bb9d39ec4e5436aa58ef6a900b8b0c13713c47d58
MD5 adf79c51a3266e428b4ed7747b2e2207
BLAKE2b-256 b8c4a7a20677b350b9444852c7b9d06a571893b235e8c86b0d978ef772807ba0

See more details on using hashes here.

Provenance

The following attestation bundles were made for peeka-0.1.10-cp312-cp312-manylinux_2_34_x86_64.whl:

Publisher: publish-pypi.yml on wwulfric/peeka

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page