A text progress bar shows how much of a long task is done. This program builds the bar as a string first, so you can see each stage, and then shows how to redraw it on one line in a terminal.
The program
def progress_bar(done, total, width=30): fraction = done / total if total else 1 filled = int(width * fraction) bar = "█" * filled + "-" * (width - filled) return f"[{bar}] {fraction:4.0%} ({done}/{total})" for done in [0, 5, 10, 15, 20]: print(progress_bar(done, 20))
[------------------------------] 0% (0/20) [███████-----------------------] 25% (5/20) [███████████████---------------] 50% (10/20) [██████████████████████--------] 75% (15/20) [██████████████████████████████] 100% (20/20)
How it works
fractionis the part that is done, from 0 to 1. Iftotalis 0, there is nothing to do, so the bar counts as full instead of dividing by zero.int(width * fraction)is how many of the 30 places to fill."█" * filledrepeats the block character that many times, and"-"fills the rest.:4.0%shows the fraction as a percentage with no decimal places, padded to 4 characters, so the line keeps the same width at 0% and at 100%.
Updating one line in the terminal
To make the bar grow in place, print it with "\r" at the start and end="". The carriage return \r moves the cursor back to the start of the line, so the next bar is written over the old one:
import time def progress_bar(done, total, width=30): fraction = done / total if total else 1 filled = int(width * fraction) bar = "█" * filled + "-" * (width - filled) return f"[{bar}] {fraction:4.0%} ({done}/{total})" total = 20 for done in range(total + 1): print("\r" + progress_bar(done, total), end="", flush=True) time.sleep(0.01) # stands in for real work print()
This block has no output shown: in a terminal you see one bar that fills up. The Run button on this page and other captured output show all 21 versions of the line. flush=True makes Python show each version at once instead of waiting until the line is finished. The final print() moves to a new line when the work is done.