Step 2: Update a ProgressBar explicitly

Not every loop hands you a clean iterable to wrap – sometimes you need to decide for yourself when and where progress has moved on. This step drops the wrapper from the previous step and drives a ProgressBar by hand.

Explicit update()
"""The explicit form: build a `ProgressBar` and `update()` it yourself.

`progressbar.progressbar()` from the previous step is a shortcut over
this. Use a `ProgressBar` as a context manager and call `update()` with the
new value wherever your own loop happens to be, instead of handing the
loop itself to a wrapper.
"""

import time

import progressbar


def main() -> None:
    with progressbar.ProgressBar() as bar:
        for i in range(100):
            time.sleep(0.01)
            bar.update(i + 1)


if __name__ == '__main__':
    main()

The previous step gave range(100) to progressbar.progressbar() and let it manage everything. Here, the loop opens the bar as a context manager with with progressbar.ProgressBar() as bar: and, on each pass through its own for loop, calls bar.update(i + 1) to report the new value itself. The with block starts the bar on entry and finishes it on exit, just as progressbar.progressbar() did implicitly in step 1. The difference is that this code decides when update() is called, so it works just as well when progress doesn’t come from iterating a sequence at all.

Next: Step 3: Give the bar a max_value.