Of course! A progress bar is a crucial tool for any script that takes a long time to run, as it provides visual feedback to the user, letting them know the program is still working and how much is left.
Here’s a comprehensive guide to using progress bars in Python, covering the most popular libraries and from simple to advanced examples.
The Quick and Easy Answer: tqdm
For 99% of use cases, tqdm (which means "progress" in Arabic) is the best choice. It's incredibly easy to use, highly customizable, and works seamlessly in scripts, notebooks, and even command-line pipes.
Installation
First, you need to install it:
pip install tqdm
Basic Usage
The simplest way to use tqdm is to wrap any iterable (like a list or a range) with it.
from tqdm import tqdm
import time
# A simple loop
for i in tqdm(range(100)):
time.sleep(0.05) # Simulate work
Running this will produce a nice progress bar in your terminal:
100%|██████████| 100/100 [00:05<00:00, 19.50it/s]
Real-World Example: Downloading Files
A very common use case is showing progress during a file download. The requests library is perfect for this.
import requests
from tqdm import tqdm
url = "https://speed.hetzner.de/100MB.bin" # A 100MB test file
response = requests.get(url, stream=True)
# Get the total file size from headers
total_size_in_bytes = int(response.headers.get('content-length', 0))
block_size = 1024 # 1 Kibibyte
# Wrap the response.iter_content with tqdm
progress_bar = tqdm(total=total_size_in_bytes, unit='iB', unit_scale=True, desc="Downloading")
with open("100MB.bin", "wb") as file:
for data in response.iter_content(block_size):
progress_bar.update(len(data))
file.write(data)
progress_bar.close()
Key Features of tqdm
- Automatic Updates: It figures out the iteration count and speed automatically.
- Context Managers: You can use it with
withstatements for more control. - Nested Bars: It supports nested loops with sub-bars.
- Notebook Integration: It works beautifully in Jupyter and Google Colab notebooks, creating a rich HTML progress bar.
- Pipes: It can monitor the progress of data being piped through a command-line script.
The Built-in Solution: print()
If you can't install external libraries, you can always create a simple text-based progress bar using just print(). This is great for simple scripts or learning purposes.
import time
def simple_progress_bar(current, total, bar_length=20):
percent = float(current) * 100 / total
arrow = '-' * int(round(percent / 100 * bar_length)-1) + '>'
spaces = ' ' * (bar_length - len(arrow))
# The '\r' character moves the cursor to the beginning of the line
print(f"Progress: [{arrow}{spaces}] {percent:.2f}%", end='\r')
total_items = 100
for i in range(total_items + 1):
simple_progress_bar(i, total_items)
time.sleep(0.05)
# Print a newline at the end to move to the next line
print("\nDone!")
How it works:
\r(Carriage Return): This is the magic character. It moves the cursor back to the start of the current line without moving down. Theend='\r'argument inprint()prevents it from adding a newline character.- The Bar: We calculate how much of the bar should be filled (
arrow) and how much should be empty (spaces). end='\r': This ensures that the nextprint()call overwrites the current line, creating the illusion of a moving bar.
The GUI Solution: tqdm with rich
If you're building a desktop application or want a beautiful, rich-text progress bar in your terminal, the rich library is an excellent choice. It can also be used as a backend for tqdm.
Installation
pip install rich
Usage
rich has its own progress manager that is very powerful.
from rich.progress import Progress
import time
# Rich has its own context manager for progress bars
with Progress() as progress:
# Add a task to the progress bar
task = progress.add_task("[cyan]Processing...", total=100)
for i in range(100):
# Simulate work
time.sleep(0.05)
# Update the progress bar
progress.update(task, advance=1)
This will produce a stunning, colorful, and informative progress bar directly in your terminal.
You can also use tqdm with the rich backend:
from tqdm import tqdm
from rich.progress import BarColumn, TextColumn, TimeRemainingColumn
# Create a custom tqdm bar using rich components
bar_format = "{l_bar}{bar}| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, {rate_fmt}]"
with tqdm(range(100), bar_format=bar_format, colour="green") as pbar:
for i in pbar:
time.sleep(0.05)
For GUI Applications: PyQt or Tkinter
If you are building a graphical user interface (GUI) with a framework like PyQt or Tkinter, you would use their native widgets.
Tkinter Example
Tkinter is Python's built-in GUI library.
import tkinter as tk
from tkinter import ttk
import time
def run_task():
progress_bar['value'] = 0
for i in range(101):
# Simulate work
time.sleep(0.05)
progress_bar['value'] = i
# Update the window to show the progress
root.update_idletasks()
# Create the main window
root = tk.Tk()"Tkinter Progress Bar")
root.geometry("300x100")
# Create a progress bar widget
progress_bar = ttk.Progressbar(root, orient="horizontal", length=200, mode="determinate")
progress_bar.pack(pady=20)
# Start the task in a way that doesn't freeze the GUI
# (For a real app, you'd use threading)
run_task()
root.mainloop()
PyQt5/PySide2 Example
PyQt is a more powerful and modern GUI framework.
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QProgressBar, QPushButton, QVBoxLayout, QWidget
from PyQt5.QtCore import QThread, pyqtSignal
import time
# Worker thread to perform the task without freezing the GUI
class Worker(QThread):
progress_updated = pyqtSignal(int)
def run(self):
for i in range(101):
time.sleep(0.05)
self.progress_updated.emit(i)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("PyQt Progress Bar")
self.setGeometry(100, 100, 300, 150)
self.progress_bar = QProgressBar()
self.button = QPushButton("Start Task")
self.button.clicked.connect(self.start_task)
layout = QVBoxLayout()
layout.addWidget(self.progress_bar)
layout.addWidget(self.button)
container = QWidget()
container.setLayout(layout)
self.setCentralWidget(container)
def start_task(self):
self.button.setEnabled(False)
self.progress_bar.setValue(0)
self.worker = Worker()
self.worker.progress_updated.connect(self.progress_bar.setValue)
self.worker.finished.connect(self.task_finished)
self.worker.start()
def task_finished(self):
self.button.setEnabled(True)
print("Task finished!")
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
Summary: Which One Should You Use?
| Scenario | Recommended Tool | Why? |
|---|---|---|
| Simple script, command line | tqdm |
Easiest to use, just wrap an iterable. Looks great by default. |
| Cannot install packages | print() with \r |
Built-in, no dependencies. Good for basic needs. |
| Terminal app with rich UI | rich |
Creates beautiful, colorful, and informative bars. |
| Jupyter Notebook / Colab | tqdm |
Works out-of-the-box with a rich HTML display. |
| Desktop GUI App | PyQt/Tkinter widgets |
The standard way to integrate progress into a graphical interface. |
| Advanced logging & CLI | rich |
More than just a progress bar; it's a full-f rich text and formatting library. |
For any new project, start with tqdm. It's the industry standard for a reason.
