SmoothingETA

SmoothingETA estimates remaining time via a recency-weighted rate.

Reach for it when per-item timing is noisy but you still want a stable estimate without the fixed sample window AdaptiveETA uses. The exponential moving average weights recent updates more than old ones without discarding history outright, and smoothing_algorithm with smoothing_parameters picks the algorithm. In the demo, each step’s timing carries random jitter, yet the countdown moves smoothly.

class progressbar.widgets.SmoothingETA(smoothing_algorithm: type[SmoothingAlgorithm] = <class 'progressbar.algorithms.ExponentialMovingAverage'>, smoothing_parameters: dict[str, float] | None=None, **kwargs)[source]

Bases: ETA

WidgetBase which estimates the ETA from an exponential moving average.

EMA applies more weight to recent data points and less to older ones, and doesn’t require storing all past values. This approach works well with varying data points and smooths out fluctuations effectively.

Instantiate the smoothing algorithm.

Parameters:
  • smoothing_algorithmSmoothingAlgorithm subclass to instantiate. Defaults to ExponentialMovingAverage.

  • smoothing_parameters – Keyword arguments passed to smoothing_algorithm’s constructor.

  • **kwargs – Forwarded to the next class in the cooperative __init__ chain.

Example

SmoothingETA
"""``SmoothingETA`` estimates remaining time via a recency-weighted rate.

Reach for it when per-item timing is noisy but you still want a stable
estimate without the fixed sample window ``AdaptiveETA`` uses -- the
exponential moving average weights recent updates more than old ones
without discarding history outright. This example adds seeded random
jitter to each step's timing over a longer run than most examples here,
since the smoothing only becomes visible across unevenly spaced
updates -- and since the ETA is only shown to whole-second resolution,
"longer" means several seconds, not merely more than a few milliseconds.
"""

import random
import time

import progressbar

random.seed(0)

STEPS = 40


def main() -> None:
    widgets = [
        progressbar.Percentage(),
        ' ',
        progressbar.Bar(),
        ' ',
        progressbar.SmoothingETA(),
    ]
    with progressbar.ProgressBar(max_value=STEPS, widgets=widgets) as bar:
        for step in range(STEPS):
            bar.update(step + 1)
            time.sleep(0.12 + random.random() * 0.12)


if __name__ == '__main__':
    main()

See also

  • AdaptiveETA: a fixed sample window instead of an exponential average.

  • ETA: the plain whole-run-average estimate this smooths.

  • AbsoluteETA: a clock time instead of a countdown.