Free, local, zero dependencies.
Ordinary progress bars assume the rest of your job looks like the part that already ran. That assumption breaks exactly when it matters: when the expensive work is at the end. So the bar says "3 minutes left," you walk away, and it's actually 3 hours.
For a loop over a known set of items, the future work already exists. Instead of guessing what's left from what you saw first, RunScope measures a tiny representative sample of the remaining items and estimates the rest with design-based survey sampling. You get an honest range, not a fake exact number.
import runscope for item in runscope.track(items, key="my_job"): process(item)
my_job |########------------| 38% 17492/48000 | 1h20m left (1h12m-1h31m) | high | [Padawan]
On heterogeneous or back-loaded jobs, a plain bar is routinely 60 to 280 percent off. RunScope cuts that to low single digits.
| workload shape | plain bar | RunScope |
|---|---|---|
| heavy tail | 60% off | 0% off |
| slow phase mid-run | 70% off | 0% off |
| front-loaded | 278% off | 1% off |
| random spikes | 64% off | 3% off |
| steady (easy) | 0% off | 0% off |
A smarter current-run estimate that reacts to slowdowns instead of hanging.
Learns a recurring job after a few runs and calibrates automatically.
Samples the upcoming work to predict heavy or uneven jobs before they surprise you.
from runscope import trange for i in trange(10000, key="my_job"): ...
RunScope is for enumerable work: files, records, images, tiles, simulations, parameter grids, API calls. It does not pretend to predict the runtime of arbitrary code, and when it can't estimate honestly, it says so instead of inventing a number. The method is design-based sampling (Horvitz-Thompson), the same statistics used for ecological abundance estimation.