Switch from tqdm without renaming your keywords

Porting a loop from tqdm means either rewriting every call site’s keyword arguments, or finding the ones that already mean the same thing here.

tqdm-style keyword arguments
"""Keep tqdm's keyword style when you switch to progressbar.

Coming from `tqdm`, these keywords mean the same thing here: `desc` becomes
the prefix and `total` becomes `max_value` on any `ProgressBar`. `unit=`/
`unit_scale=` only show up through a widget that reads them, such as
`UnitProgress`, so this lists one explicitly alongside `Postfix` for the
live per-file status.
"""

import time

import progressbar

STEPS = 24


def main() -> None:
    widgets = [
        progressbar.Percentage(),
        ' ',
        progressbar.Bar(),
        ' ',
        progressbar.UnitProgress(),
        ' ',
        progressbar.Postfix(),
    ]
    with progressbar.ProgressBar(
        desc='Downloading',
        total=STEPS,
        unit='files',
        widgets=widgets,
        postfix='starting',
    ) as bar:
        for step in range(STEPS):
            bar.update(step + 1, postfix=f'file {step + 1}')
            time.sleep(0.005)


if __name__ == '__main__':
    main()

desc and total work on any ProgressBar: desc becomes the prefix (rendered as f'{desc}: '), and total becomes max_value when max_value isn’t given explicitly. unit=/unit_scale= don’t render anything by themselves – they only show up through a widget that reads them, such as UnitProgress() – so pass a widget list that includes one if you want them visible, as this demo does alongside Postfix() for the live per-file status.

Caveats

Not every tqdm keyword carries over. An unrecognized one, such as ncols, is silently accepted rather than raising – it has no effect and nothing warns you it was ignored, so a typo in a keyword name fails quietly instead of loudly.