Stage-aware progress monitoring for parallel Python jobs
Project description
ProgressBox
Stage-aware progress monitoring for parallel Python jobs.
Features
- Stage-aware tracking - Monitor different stages of computation with timing analysis
- True parallelism - Built for multiprocessing, threading, and joblib
- Rich statistics - ETA, throughput, stage timing breakdown
- Multiple renderers - Terminal, Jupyter notebooks, or plain string output
- Production ready - Logging, snapshots, callbacks, error handling
Installation
pip install progressbox
For development:
git clone https://github.com/yourorg/progressbox.git
cd progressbox
pip install -e .
Quick Start
Basic Usage
from progressbox import Progress, Config
config = Config(total=100, n_workers=4)
with Progress(config) as progress:
for i in range(100):
progress.task_start(f"task_{i}")
# ... do work ...
progress.task_finish(f"task_{i}")
With Stages
Track different phases of each task:
from progressbox import Progress, Config
config = Config(total=100)
with Progress(config) as progress:
for i in range(100):
progress.task_start(f"task_{i}")
progress.task_update(f"task_{i}", stage="loading")
data = load_data(i)
progress.task_update(f"task_{i}", stage="processing")
result = process(data)
progress.task_update(f"task_{i}", stage="saving")
save(result)
progress.task_finish(f"task_{i}")
With Callbacks
Get notified on completion:
from progressbox import Progress, Config
def on_complete(snapshot):
print(f"Processed {snapshot['completed']} tasks")
print(f"Total time: {snapshot['elapsed']:.1f}s")
config = Config(total=100, on_complete=on_complete)
with Progress(config) as progress:
# ... process tasks ...
Display Example
+======================================================================+
| Progress Monitoring |
+======================================================================+
| Progress: [################............] 42/100 (42%) |
| Elapsed: 1m 23s | ETA: 1m 52s | Rate: 0.5 tasks/s |
+----------------------------------------------------------------------+
| Stage Analysis |
| loading: 0.8s avg (32%) |
| processing: 1.2s avg (48%) |
| saving: 0.5s avg (20%) |
+----------------------------------------------------------------------+
| Active Workers |
| W0: processing [####....] 1.2s |
| W1: loading [##......] 0.3s |
| W2: saving [######..] 0.4s |
+======================================================================+
Configuration Reference
Config(
# Required
total=100, # Total number of tasks
# Display options
n_workers=6, # Number of worker rows to display
inner_width=68, # Display width (60, 68, 84, 100, or "auto")
unicode=True, # Use Unicode box characters
renderer="ascii", # "ascii", "string", "jupyter", or "rich"
# Feature toggles
show_stage_analysis=True, # Show stage timing breakdown
show_workers=True, # Show active worker list
max_active_rows=12, # Max worker rows to display
# Performance
refresh_hz=8.0, # Display refresh rate
display_interval=0.1, # Minimum time between renders
# Metrics
ewma_alpha=0.2, # ETA smoothing factor
cache_speed_factor=0.8, # Speed adjustment for cached tasks
# Production settings
fail_safe=True, # Never raise exceptions
headless_ok=True, # Allow headless operation
prod_safe=False, # Conservative mode for production
# Callbacks
on_snapshot=None, # Called periodically with state
on_complete=None, # Called when all tasks complete
snapshot_interval_s=10.0, # Seconds between snapshots
log_interval_s=30.0, # Seconds between log messages
)
API Reference
Progress Class
from progressbox import Progress, Config
config = Config(total=100)
progress = Progress(config)
# Context manager (recommended)
with Progress(config) as p:
p.task_start(task_id)
p.task_update(task_id, stage="working")
p.task_finish(task_id)
# Manual control
progress.start() # Start rendering
progress.stop() # Stop rendering (keeps state)
progress.close() # Final cleanup
progress.tick() # Force render update
Task Methods
# Start tracking a task
progress.task_start(
task_id, # Unique task identifier
worker=None, # Worker ID (auto-assigned if None)
cached=False, # Whether task uses cached results
meta=None # Optional metadata dict
)
# Update task state
progress.task_update(
task_id,
stage=None, # New stage name
progress=None, # Progress ratio (0.0-1.0)
sub_progress=None # Sub-progress as (current, total)
)
# Mark task complete
progress.task_finish(task_id)
# Aliases
progress.stage_transition(task_id, stage) # Same as task_update with stage
progress.stage_progress(task_id, ratio) # Same as task_update with progress
progress.task_complete(task_id) # Same as task_finish
Helper Functions
from progressbox import create_default_config
# Create config with sensible defaults
config = create_default_config(
total=100,
n_workers=8,
renderer="string"
)
Renderers
ProgressBox automatically selects the best renderer for your environment:
| Environment | Default Renderer |
|---|---|
| Terminal (TTY) | ascii - Unicode box drawing |
| Jupyter notebook | jupyter - HTML with styling |
| Headless/CI | string - Plain text |
Force a specific renderer:
config = Config(total=100, renderer="string")
Joblib Integration
from joblib import Parallel, delayed
from progressbox.adapters import joblib_progress
def process(item):
# Your processing function
return result
items = list(range(100))
with joblib_progress(total=len(items)) as progress:
results = Parallel(n_jobs=4)(
delayed(process)(item) for item in items
)
Thread Safety
All task methods (task_start, task_update, task_finish) are thread-safe and can be called from multiple workers concurrently.
Error Handling
By default, ProgressBox operates in fail-safe mode (fail_safe=True), catching and logging errors without interrupting your workflow. For strict error handling:
config = Config(total=100, fail_safe=False)
License
MIT License - see LICENSE file for details.
Project details
Release history Release notifications | RSS feed
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 progressbox-0.1.0.tar.gz.
File metadata
- Download URL: progressbox-0.1.0.tar.gz
- Upload date:
- Size: 62.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cc5e1be90057a2f1769f3e6ee5f5ff092c8bb3d5123c179696ee55c465db6a64
|
|
| MD5 |
5fcee8fbf7109e1fb51aee108deed0cc
|
|
| BLAKE2b-256 |
2465c6f3d1e15ecb7aa9d3098e4f3404a5d5ef4babc464e730000d350e5e43af
|
Provenance
The following attestation bundles were made for progressbox-0.1.0.tar.gz:
Publisher:
publish.yml on ZaafirH/progressbox
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
progressbox-0.1.0.tar.gz -
Subject digest:
cc5e1be90057a2f1769f3e6ee5f5ff092c8bb3d5123c179696ee55c465db6a64 - Sigstore transparency entry: 854972238
- Sigstore integration time:
-
Permalink:
ZaafirH/progressbox@700bb2c7df7682238242110776408d8025b5aef1 -
Branch / Tag:
refs/tags/v0.1.0.a - Owner: https://github.com/ZaafirH
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@700bb2c7df7682238242110776408d8025b5aef1 -
Trigger Event:
release
-
Statement type:
File details
Details for the file progressbox-0.1.0-py3-none-any.whl.
File metadata
- Download URL: progressbox-0.1.0-py3-none-any.whl
- Upload date:
- Size: 57.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6cf695d7d11e311452f92ace404af2f75e01bd367f9efb2169156cb1c9f47fe0
|
|
| MD5 |
4858d460887a79897933ec9bb5e8ddc5
|
|
| BLAKE2b-256 |
b446ff09d10e0b20b1dcd9a71d740f0f2ef9258af4765b115b2d74b7e98c7e8f
|
Provenance
The following attestation bundles were made for progressbox-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on ZaafirH/progressbox
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
progressbox-0.1.0-py3-none-any.whl -
Subject digest:
6cf695d7d11e311452f92ace404af2f75e01bd367f9efb2169156cb1c9f47fe0 - Sigstore transparency entry: 854972239
- Sigstore integration time:
-
Permalink:
ZaafirH/progressbox@700bb2c7df7682238242110776408d8025b5aef1 -
Branch / Tag:
refs/tags/v0.1.0.a - Owner: https://github.com/ZaafirH
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@700bb2c7df7682238242110776408d8025b5aef1 -
Trigger Event:
release
-
Statement type: