Show a custom value next to the bar

When you scan a log, the number of errors matters alongside the number of records inspected. A Variable widget displays the error count while the percentage tracks the scan:

Errors found while scanning logs
"""Count errors while scanning log records with a Variable widget.

The bar counts inspected records. The named variable counts only the
records that contain an error, so the two readings describe different
parts of the same job.
"""

import time

import progressbar
from progressbar.widgets import WidgetBase

RECORDS: list[str] = [
    'INFO request received',
    'INFO cache hit',
    'ERROR request timed out',
    'INFO response sent',
    'INFO connection closed',
] * 20


def main() -> None:
    widgets: list[str | WidgetBase] = [
        progressbar.Variable('errors', format='Errors: {value:2.0f}'),
        ' | Scanned ',
        progressbar.Percentage(),
        ' ',
        progressbar.Bar(),
    ]
    errors: int = 0
    bar: progressbar.ProgressBar
    step: int
    record: str
    with progressbar.ProgressBar(
        max_value=len(RECORDS), widgets=widgets, variables={'errors': 0}
    ) as bar:
        for step, record in enumerate(RECORDS, start=1):
            errors += record.startswith('ERROR')
            time.sleep(0.02)
            bar.update(step, errors=errors)


if __name__ == '__main__':
    main()

Variable('errors') reads the errors= keyword passed to bar.update(). The example increments that count only when a record starts with ERROR. The scan finishes at 100% with 20 errors found among 100 records. Placing the count first keeps it beside the scan percentage as the bar stretches to fill the remaining width.

variables={'errors': 0} supplies the initial reading. Without an initial value, the bar registers a placeholder for each Variable in its widget list and displays dashes until the first update.

Older code may import DynamicMessage. It is a plain subclass of Variable, kept for compatibility, and behaves identically. Use Variable in new code.