How to create Progress Bars in Python with Examples


Python

Welcome to this comprehensive guide on Python progress bars! Whether you're a seasoned coder or just dipping your toes into the world of Python programming, you've likely come across tasks that take a while to complete. From large data manipulations to web scraping, these tasks can be time-consuming, and waiting for them to finish can be a dull affair. This is where a progress bar comes into play.

A Python progress bar is not just a neat visual element; it serves a practical purpose. It offers real-time feedback on the status of ongoing tasks, helps in estimating how much longer an operation will take, and improves the overall user experience. In this guide, we will delve deep into various ways to implement and customize progress bars in Python, catering to all skill levels.

 

How to Create a Simple Python Progress Bar?

Here's a simple Python code snippet to display a text-based Python progress bar.

import time
import sys

def display_progress_bar(iteration, total, bar_length=50):
    progress = (iteration / total)
    arrow = '=' * int(round(progress * bar_length) - 1)
    spaces = ' ' * (bar_length - len(arrow))

    sys.stdout.write(f'\rProgress: [{arrow + spaces}] {int(progress * 100)}%')
    sys.stdout.flush()

# Test the progress bar
total = 100
for i in range(total + 1):
    time.sleep(0.1)  # Simulate some work
    display_progress_bar(i, total)

Explanation:

  1. Import Modules: We import time for simulating some work and sys for updating the text in the terminal.
  2. Function display_progress_bar:
    • Parameters:
      • iteration: Current iteration
      • total: Total iterations
      • bar_length: Length of the progress bar (default is 50)
    • Inside the Function:
      • We calculate progress as the ratio of iteration to total.
      • arrow is a string of '=' characters to indicate progress.
      • spaces is a string of spaces to fill the rest of the bar.
    • Display: We use sys.stdout.write and sys.stdout.flush to update the same line in the terminal.
  3. Test the Progress Bar:
    • The loop from 0 to total simulates a task.
    • We call display_progress_bar with the current iteration and total number of iterations.

 

Different methods to generate a Python Progress Bar

1. Built-In Methods

  • Print Statement: Use the standard print() function with carriage returns (\r) to update a text-based progress bar in the terminal.
  • String Concatenation: Build and update a string that visually represents the progress bar, then print it.

2. Third-Party Libraries

  • tqdm: A fast, extensible Python progress bar library that wraps around iterable objects.
  • progress: Offers customizable text-based progress bars with various styles.
  • alive-progress: Provides animated and highly customizable progress bars.
  • progressbar2: An extensible library for creating customizable Python progress bars with a variety of features.
  • rich: A library not only for progress bars but also for rich text and beautiful formatting in the terminal.

3. GUI Libraries

  • PySimpleGUI: Allows you to create a graphical Python progress bar within a PySimpleGUI window.
  • PyQt: Integrate a Python progress bar in a PyQt-based GUI application.
  • Tkinter: Use Tkinter to create a simple graphical progress bar.
  • Kivy: Implement Python progress bars in applications designed using the Kivy framework.

4. Web-Based Methods

  • Flask with JavaScript: Use Flask back-end and JavaScript front-end to show progress bars for web tasks.
  • Django Channels: Implement real-time Python progress bars in a Django application by using Django Channels for WebSocket support.

 

1. Using Built-in Solutions

1.1. Using for loop and print()

The simplest way to create a text-based Python progress bar is by using Python's built-in print() function along with a for loop.

import sys
import time  # Importing time library for sleep

total_iterations = 100

for i in range(total_iterations + 1):
    time.sleep(0.1)  # Sleep for 100 milliseconds
    percentage_complete = (i / total_iterations) * 100
    print("Progress: {:.2f}%".format(percentage_complete), end='\r')
    sys.stdout.flush()
  • total_iterations = 100: This sets up how many iterations the loop will go through, representing the total amount of work to be done.
  • for i in range(total_iterations + 1): A for loop iterates from 0 to total_iterations (inclusive). Each iteration simulates a unit of work being done.
  • time.sleep(0.1): This line pauses the loop for 0.1 seconds (100 milliseconds) on each iteration. This is to simulate the time that would normally be spent doing some kind of work, making it easier to observe the progress bar.
  • percentage_complete = (i / total_iterations) * 100: Calculates what percentage of the total work has been completed after each iteration.
  • print("Progress: {:.2f}%".format(percentage_complete), end='\r'): Prints the progress. The end='\r' means it will overwrite the current line in the terminal, creating a "dynamic" line that updates.
  • sys.stdout.flush(): Forces the standard output to be displayed immediately, ensuring that the progress is visibly updated in real-time.

 

1.2. Using time.sleep() for Simulation

The time.sleep() function can be used to simulate the time taken for a task to complete. It's often helpful to use it when demonstrating a Python progress bar.

import time

total_iterations = 100

for i in range(total_iterations + 1):
    time.sleep(0.1)  # Simulating time delay for each task
    percentage_complete = (i / total_iterations) * 100
    print("Progress: {:.2f}%".format(percentage_complete), end='\r')

Explanation:

  • import time: We import the time module for its sleep() function.
  • time.sleep(0.1): We use time.sleep(0.1) to pause the program for 0.1 seconds on each iteration of the loop, simulating time taken for a task to complete.

 

2. Using Third Party Solutions

2.1 Using tqdm

The tqdm library offers a fast and extensible way to create a Python progress bar. You can install it via pip:

pip3 install tqdm

2.1.1: Basic Progress Bar Using for loop and print()

Once installed, using tqdm is straightforward. Just wrap it around any iterable, and you'll get an automatic progress bar.

from tqdm import tqdm
import time

for i in tqdm(range(100)):
    time.sleep(0.1)

In this example, tqdm automatically generates a Python progress bar and updates it in real-time as the loop iterates.

Explanation

  • from tqdm import tqdm: This imports the tqdm function from the tqdm library.
  • for i in tqdm(range(100)): tqdm wraps around Python's range function. This provides you with a progress bar for 100 iterations.
  • time.sleep(0.1): Pauses the loop for 0.1 seconds to simulate some work being done.

When you run the code, you'll see an output similar to the following in your terminal:

100%|██████████| 100/100 [00:10<00:00,  9.59it/s]
  • 100%: Shows that 100 out of 100 iterations are completed.
  • [00:10<00:00, 9.59it/s]: Indicates that it took 10 seconds to complete 100 iterations, with an average speed of approximately 9.59 iterations per second.

2.1.2: Custom Description and Unit

from tqdm import tqdm
import time

for i in tqdm(range(100), desc="Processing", unit="iteration"):
    time.sleep(0.1)

2.1.3: Nested Progress Bars

from tqdm import tqdm
import time

for i in tqdm(range(10), desc="Outer Loop"):
    for j in tqdm(range(100), desc="Inner Loop", leave=False):
        time.sleep(0.01)

2.1.4: File Download Progress

from tqdm import tqdm
import requests

url = "https://example.com/large-file.zip"
response = requests.get(url, stream=True)

with open("large-file.zip", "wb") as f, tqdm(
    unit="B", 
    unit_scale=True, 
    unit_divisor=1024, 
    total=int(response.headers.get('content-length', 0))
) as bar:
    for data in response.iter_content(chunk_size=1024):
        bar.update(len(data))
        f.write(data)

2.1.5: Asynchronous Progress Bars

import asyncio
from tqdm.asyncio import tqdm

async def some_task(n):
    await asyncio.sleep(n)

async def main():
    tasks = [some_task(i) for i in range(5)]
    for f in tqdm.as_completed(tasks, desc="Processing", unit="task"):
        await f

if __name__ == '__main__':
    asyncio.run(main())

2.1.6: Using tqdm with pandas DataFrame

tqdm can also be integrated with pandas DataFrames to show progress when applying a function row-wise or column-wise.

pip3 install pandas

Code Example

import pandas as pd
from tqdm import tqdm

# Create a DataFrame
df = pd.DataFrame({'A': range(1, 101), 'B': range(101, 201)})

# Use tqdm to show progress
tqdm.pandas()

df['C'] = df['A'].progress_apply(lambda x: x * 2)

Explanation

  • tqdm.pandas(): This modifies pandas to include progress_apply, a variant of the apply function that shows progress.
  • df['C'] = df['A'].progress_apply(lambda x: x * 2): Here, we apply a function to double each value in column A, and the progress is displayed thanks to progress_apply.

2.1.7: Using tqdm for File Downloading

Imagine you're downloading multiple files and you want to keep track of the progress.

import requests
from tqdm import tqdm

urls = ['https://example.com/file1.zip', 'https://example.com/file2.zip']

for url in tqdm(urls, desc="Downloading files"):
    response = requests.get(url)
    with open(url.split('/')[-1], 'wb') as f:
        f.write(response.content)

Explanation

  • for url in tqdm(urls, desc="Downloading files"): Here, we loop through a list of URLs to download, and tqdm tracks the progress.
  • response = requests.get(url): Using the requests library to fetch the content of the URL.
  • f.write(response.content): Writing the content to a file.

2.1.8: Using tqdm with Generators

You can also use tqdm with Python generators.

from tqdm import tqdm

def data_stream():
    for i in range(100):
        yield i

stream = data_stream()

for i in tqdm(stream, total=100):
    time.sleep(0.1)

Explanation

  • def data_stream(): This is a generator function that yields numbers from 0 to 99.
  • for i in tqdm(stream, total=100): We pass the generator stream to tqdm, along with total=100 which specifies the total number of items in the generator.

 

2.2 Using Progressbar2

progressbar2 is another Python library for creating visual (text-based) Python progress bars. Let's dive into its installation, basic usage, and customization options, offering both basic and advanced examples for each.

Firstly, you'll need to install the library. Open your terminal or command prompt and run:

pip3 install progressbar2

2.2.1 Basic Usage

After the installation, you can create a simple Python progress bar using the following code:

import time
from progressbar import ProgressBar

bar = ProgressBar(max_value=100)
for i in range(101):
    time.sleep(0.1)
    bar.update(i)

Basic Explanation

  • ProgressBar(max_value=100): Initializes a new progress bar with a maximum value of 100.
  • bar.update(i): Updates the progress bar to the current value of i.

You'll see a text-based Python progress bar on the terminal that fills up as the loop progresses.

2.2.2: Custom Widgets

import time

from progressbar import ProgressBar, Percentage, Bar, RotatingMarker, ETA

widgets = ['Progress: ', Percentage(), ' ', Bar(marker=RotatingMarker()), ' ', ETA()]

bar = ProgressBar(widgets=widgets, max_value=100).start()

for i in range(101):
    time.sleep(0.1)
    bar.update(i)

Explanation

  • widgets = [...]: This list defines the widgets that will appear in the Python progress bar. Here we include the progress percentage, a rotating marker bar, and an estimated time of arrival (ETA).
  • ProgressBar(widgets=widgets, max_value=100).start(): Initializes the progress bar with custom widgets and starts it.

2.2.3: Adaptive Progress Bar

import time

from progressbar import AdaptiveETA, ProgressBar, Timer

widgets = ['Elapsed Time: ', Timer(), ' | ETA: ', AdaptiveETA()]

bar = ProgressBar(widgets=widgets, max_value=100).start()

for i in range(101):
    time.sleep(0.1)
    bar.update(i)

Advanced Explanation

  • AdaptiveETA: Unlike ETA, which gives an estimated completion time based on all the data so far, AdaptiveETA provides a more accurate estimate by considering only recent progress.
  • Timer(): This widget shows the elapsed time since the Python progress bar started.

2.2.4: Downloading Files with progressbar2

Let's assume you are downloading multiple files and want to show progress:

import requests
import progressbar

urls = [
    "https://example.com/file1.zip",
    "https://example.com/file2.zip",
    "https://example.com/file3.zip"
]

with progressbar.ProgressBar(max_value=len(urls)) as bar:
    for i, url in enumerate(urls):
        response = requests.get(url)
        with open(f"file_{i + 1}.zip", "wb") as f:
            f.write(response.content)
        bar.update(i)

In this example, we use progressbar.ProgressBar(max_value=len(urls)) to create a Python progress bar with a maximum value corresponding to the number of URLs.

2.2.5: Custom Widgets and Formatting

progressbar2 allows you to use custom widgets to display more detailed information.

import time
import progressbar

widgets=[
    ' [', progressbar.Timer(), '] ',
    progressbar.Bar(),
    ' (', progressbar.ETA(), ') ',
]

with progressbar.ProgressBar(max_value=100, widgets=widgets) as bar:
    for i in range(100):
        time.sleep(0.1)
        bar.update(i)

Here, Timer will show the elapsed time, Bar is the Python progress bar itself, and ETA will show the estimated time to completion.

2.2.6: Adaptive ETA

You can use the AdaptiveETA widget to get a more accurate ETA based on recent progress.

widgets = [
    progressbar.Percentage(),
    ' ', progressbar.AdaptiveETA(),
    ' ', progressbar.Bar()
]

with progressbar.ProgressBar(max_value=100, widgets=widgets) as bar:
    for i in range(100):
        time.sleep(0.1)
        bar.update(i)

In this example, AdaptiveETA will adjust the ETA calculation to be more accurate based on recent updates.

2.2.7: Custom Progress Bar Styles

You can fully customize your Python progress bar using the progressbar.Bar class:

widgets = [
    'Processing: ', progressbar.Counter(), ' items',
    ' ', progressbar.Bar(marker=progressbar.RotatingMarker(markers='◐◓◑◒')),
    ' ', progressbar.Percentage(),
    ' ', progressbar.AdaptiveETA()
]

with progressbar.ProgressBar(max_value=100, widgets=widgets) as bar:
    for i in range(100):
        time.sleep(0.1)
        bar.update(i)

In this example, we define a rotating marker style for the progress bar using RotatingMarker.

 

2.3 Using Progress Library

The progress library is another package to create text-based progress bars in Python. Below, you'll find details about its installation, basic usage, and customization, with examples ranging from basic to advanced.

The installation process is straightforward. Open your terminal and execute the following command:

pip3 install progress

2.3.1: Basic Usage

Once you've installed the package, creating a basic Python progress bar is simple.

from progress.bar import Bar
import time

bar = Bar('Processing', max=100)
for i in range(100):
    time.sleep(0.1)
    bar.next()
bar.finish()

Explanation

  • Bar('Processing', max=100): This initializes a new progress bar object with the label "Processing" and a maximum value of 100.
  • bar.next(): This method updates the progress bar by one step.
  • bar.finish(): This completes the progress bar.

Running this code will display a text-based Python progress bar in your terminal, filling up as the loop iterates.

2.3.2: Custom Bar

from progress.bar import ChargingBar

bar = ChargingBar('Charging', max=100, suffix='%(percent)d%%')

for i in range(100):
    time.sleep(0.1)
    bar.next()
bar.finish()

Explanation

  • ChargingBar('Charging', max=100, suffix='%(percent)d%%'): This initializes a different style of bar (ChargingBar) and sets a custom suffix to display the percentage completion.

2.3.3: Filling Pie

from progress.spinner import PieSpinner

spinner = PieSpinner('Cooking ')

for i in range(100):
    time.sleep(0.1)
    spinner.next()

Explanation

  • PieSpinner('Cooking '): This initializes a pie spinner, which is another way to indicate progress.
  • spinner.next(): Advances the spinner by one frame.

Unlike a Python progress bar, a spinner doesn't give a sense of how much work remains, but it does indicate that work is being done.

2.3.4: File Transfer Example with Bar

Let's assume you're transferring files and want to display a Python progress bar for this operation.

from progress.bar import Bar
import shutil

bar = Bar('Transferring Files', max=10, suffix='%(index)d/%(max)d - %(percent).1f%% - %(eta)ds')

for i in range(1, 11):
    # Simulate file transfer by copying a file
    shutil.copy('source_file.txt', f'destination_file_{i}.txt')
    bar.next()
bar.finish()

Parameters Used:

  • suffix: The custom string that appears to the right of the Python progress bar, displaying additional information such as the current index, max value, percentage, and estimated time to completion (eta).

2.3.5: Data Processing with ChargingBar

Imagine you are processing rows in a dataset:

from progress.bar import ChargingBar

bar = ChargingBar('Processing Rows', max=100, fill='@', suffix='%(percent)d%%')

for i in range(100):
    # Simulate data processing
    processed_data = i * 2
    bar.next()
bar.finish()

Parameters Used:

  • fill: Specifies the character to fill the progress bar. Here, we're using @.

2.3.6: Loading Items from API with IncrementalBar

Let's say you're loading items from an API in chunks:

from progress.bar import IncrementalBar

bar = IncrementalBar('Loading Items', max=100, suffix='%(index)d/%(max)d - %(percent).1f%% - %(eta)ds')

for i in range(100):
    # Simulate loading items from an API
    items = ["item_" + str(i) for i in range(i, i+10)]
    bar.next()
bar.finish()

Parameters Used:

  • suffix: Same as before, it shows various details next to the Python progress bar.

2.3.7: Downloading with ShadyBar

For a different style, let's use ShadyBar while downloading files:

from progress.bar import ShadyBar
import requests

bar = ShadyBar('Downloading', max=3)

urls = ['https://example.com/file1.txt', 'https://example.com/file2.txt', 'https://example.com/file3.txt']

for url in urls:
    # Simulate file download
    response = requests.get(url)
    with open(url.split('/')[-1], 'wb') as f:
        f.write(response.content)
    bar.next()
bar.finish()

Parameters Used:

  • max: Sets the maximum value for the progress bar. Useful for cases where you know the number of iterations beforehand.

 

2.4 alive-progress: A lively progress bar for Python

alive-progress is a flexible and extensible Python progress bar library that brings your command-line applications to life. It offers different styles, spinners, and customization options.

First things first, you can install alive-progress by running:

pip3 install alive-progress

2.4.1: Basic Usage

A simple example would be to wrap the alive_bar around a loop to indicate its progress:

from alive_progress import alive_bar
import time

with alive_bar(100) as bar:
    for i in range(100):
        time.sleep(0.1)
        bar()

Explanation

  • with alive_bar(100) as bar: initializes a new progress bar with a maximum of 100 iterations.
  • bar() updates the progress bar by one step each time it is called.

2.4.2: Custom Title and Spinner

Here's how you can set a custom title and spinner style:

with alive_bar(100, title='Custom', spinner='bouncingBar') as bar:
    for i in range(100):
        time.sleep(0.1)
        bar()

Parameters

  • title: Sets a custom title that appears beside the progress bar.
  • spinner: Sets a custom spinner style. Here, bouncingBar makes the spinner look like a bouncing bar.

2.4.3: Custom Bar Style

You can also customize the bar style:

with alive_bar(100, bar='blocks') as bar:
    for i in range(100):
        time.sleep(0.1)
        bar()

Parameters

  • bar: Changes the type of the bar. Here, blocks gives a solid block appearance to the bar.

2.4.4: Advanced Usage with Multiple Parameters

You can also combine multiple parameters to create a more informative and stylish Python progress bar:

with alive_bar(100, title='Processing', spinner='dots_waves2', bar='smooth', length=40) as bar:
    for i in range(100):
        time.sleep(0.1)
        bar(text=f'Item {i+1} processed')

Parameters

  • length: Sets the length of the bar in characters.
  • text: Adds a custom message beside the Python progress bar, useful for displaying additional information.

2.4.5: Nested Progress Bars

For operations that require nested loops, alive-progress provides nested Python progress bars:

with alive_bar(5, title='Outer Loop') as outer:
    for i in range(5):
        with alive_bar(20, title='Inner Loop') as inner:
            for j in range(20):
                time.sleep(0.05)
                inner()
        outer()

2.4.6: File I/O Operations

You can use alive-progress to track file I/O operations such as reading large files.

with open('large_file.txt', 'r') as file:
    lines = sum(1 for line in file)

with alive_bar(lines, title='Reading Large File') as bar:
    with open('large_file.txt', 'r') as file:
        for line in file:
            # Perform some operation on each line
            process_line(line)
            bar()

2.4.7: Data Transfer

Let's say you want to track the progress of data transfer between a server and a client:

import requests

with alive_bar(100, title='Downloading Files') as bar:
    for i in range(1, 101):
        url = f'https://example.com/file_{i}.txt'
        response = requests.get(url)
        with open(f'file_{i}.txt', 'wb') as f:
            f.write(response.content)
        bar()

2.4.8: Web Scraping

When scraping websites, you often don't know how many pages or items you'll scrape. The alive-progress library allows for an unknown total, which you can update as you go:

with alive_bar(unknown='Indeterminate', title='Web Scraping') as bar:
    while more_pages_to_scrape():
        # Scrape the page
        scrape_page()
        bar()

Here, unknown='Indeterminate' allows for a bar that can be updated without a known total.

2.4.9: Batch Processing

You might also be running batch operations that include multiple steps. Here's an example:

steps = ['Fetching Data', 'Processing', 'Storing']

with alive_bar(len(steps), title='Batch Operations', bar='blocks') as bar:
    for step in steps:
        # Execute each step
        execute_step(step)
        bar(text=f'Completed: {step}')

In this example, each batch operation updates the progress bar and sets the text to indicate which step has been completed.

2.4.10: CPU-Intensive Computations

For scientific computations or other CPU-intensive tasks, you can use alive-progress to keep track of the process.

import numpy as np

with alive_bar(100, title='Matrix Multiplication') as bar:
    for i in range(100):
        a = np.random.rand(100, 100)
        b = np.random.rand(100, 100)
        c = np.dot(a, b)
        bar()

2.4.11: Real-time Monitoring

You can use alive-progress for real-time monitoring tasks. For instance, monitoring a folder for new files:

import os
import time

with alive_bar(unknown='Indeterminate', title='Monitoring Folder') as bar:
    while True:
        # Check for new files
        new_files = check_new_files()
        if new_files:
            bar(text=f'New files detected: {len(new_files)}')
        time.sleep(5)

 

3. Using GUI Libraries

3.1 PySimpleGUI: A Simple Yet Powerful GUI Toolkit

PySimpleGUI is a Python library that simplifies the process of creating Graphical User Interfaces (GUIs). It's built on top of other GUI toolkits like Tkinter, PyQt, and WxPython, offering a more straightforward and Pythonic interface. This can be also used to create Python Progress Bar.

To install PySimpleGUI, run the following command:

pip3 install PySimpleGUI

3.1.1: Basic Usage: A Simple Window

import PySimpleGUI as sg

layout = [[sg.Text('Hello, world!')],
          [sg.Button('OK')]]

window = sg.Window('My Window', layout)

while True:
    event, values = window.read()
    if event == sg.WINDOW_CLOSED or event == 'OK':
        break

window.close()

Explanation

  • sg.Text('Hello, world!'): Adds a text element that says "Hello, world!".
  • sg.Button('OK'): Adds an "OK" button.
  • sg.Window('My Window', layout): Creates a window with the specified layout.
  • window.read(): Waits for an event (like a button click).

3.1.2: Customization: Buttons, Input Fields, and More

layout = [[sg.Text('Enter your name:'), sg.InputText()],
          [sg.Submit(), sg.Cancel()]]

window = sg.Window('Simple Input', layout)

while True:
    event, values = window.read()
    if event in (sg.WINDOW_CLOSED, 'Cancel'):
        break
    if event == 'Submit':
        sg.popup(f'Hello, {values[0]}!')

window.close()

Explanation

  • sg.InputText(): Adds an input field.
  • sg.Submit(), sg.Cancel(): Adds "Submit" and "Cancel" buttons.
  • values[0]: The text entered into the first input field (array index 0).

3.1.3: Advanced Usage: Tabs, Tables, and Dynamic Updates

layout = [[sg.TabGroup([[sg.Tab('Tab 1', [[sg.Text('I am in tab 1')]]),
                         sg.Tab('Tab 2', [[sg.Text('I am in tab 2')]])]])],
          [sg.Button('Read')]]

window = sg.Window('Tabs Example', layout)

while True:
    event, values = window.read()
    if event == sg.WINDOW_CLOSED:
        break

window.close()

In this example, we add tabs to the window. Each tab contains its layout.

3.1.4: Dynamic Updates

layout = [[sg.Text('Counter'), sg.Text('0', key='-COUNTER-')],
          [sg.Button('Increment'), sg.Button('Exit')]]

window = sg.Window('Counter Example', layout)

counter = 0
while True:
    event, values = window.read()
    if event == sg.WINDOW_CLOSED or event == 'Exit':
        break
    if event == 'Increment':
        counter += 1
        window['-COUNTER-'].update(counter)

window.close()

In this example, a counter is incremented each time the 'Increment' button is clicked, and the window is dynamically updated using window['-COUNTER-'].update(counter).

3.1.5: File Browser and Upload Example

You can also create file browsers using PySimpleGUI:

layout = [[sg.Text('Choose a file:'), sg.Input(), sg.FileBrowse()],
          [sg.OK(), sg.Cancel()]]

window = sg.Window('File Browser', layout)

while True:
    event, values = window.read()
    if event in (sg.WINDOW_CLOSED, 'Cancel'):
        break
    if event == 'OK':
        sg.popup(f'You chose {values[0]}')

window.close()

In this example, a file browser is integrated into the GUI. You can browse files, and upon clicking 'OK', the chosen file's name is displayed.

3.1.6: Real-time Monitoring / Streaming Data

You can also create applications that update in real-time:

import random

layout = [[sg.Text('Real-time data')],
          [sg.Text(size=(15, 1), key='-OUTPUT-')],
          [sg.Exit()]]

window = sg.Window('Real-time Data Example', layout)

while True:
    event, values = window.read(timeout=100)
    if event == sg.WINDOW_CLOSED or event == 'Exit':
        break
    random_data = random.randint(1, 100)
    window['-OUTPUT-'].update(random_data)

window.close()

Here, the window updates every 100 milliseconds with random data between 1 and 100.

 

3.2 PyQt: A Comprehensive Framework for GUI Development

PyQt is a set of Python bindings for the Qt libraries which can be used to create cross-platform mobile and desktop applications. It's widely used and provides tools to build both basic and complex GUIs.

To install PyQt5, you can execute the following command:

pip3 install PyQt5

3.2.1: Basic Usage: Creating a Simple Window

from PyQt5.QtWidgets import QApplication, QWidget

app = QApplication([])

window = QWidget()
window.setWindowTitle('Simple Window')
window.show()

app.exec_()

Explanation

  • QApplication([]): Initializes the PyQt5 application. You can pass command-line arguments as a list.
  • QWidget(): Creates a top-level window.
  • window.show(): Displays the window.
  • app.exec_(): Enters the event loop, waiting for user interaction.

3.2.2: Widgets and Layouts: Button and Label

from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QLabel

def on_button_click():
    label.setText("Hello, PyQt!")

app = QApplication([])

window = QWidget()
layout = QVBoxLayout()

button = QPushButton("Click Me")
button.clicked.connect(on_button_click)
layout.addWidget(button)

label = QLabel("Hello, World!")
layout.addWidget(label)

window.setLayout(layout)
window.show()

app.exec_()

Explanation

  • QPushButton("Click Me"): Creates a button with text "Click Me".
  • button.clicked.connect(on_button_click): Connects button click event to the function.
  • QLabel("Hello, World!"): Creates a label with text "Hello, World!".
  • QVBoxLayout(): Vertical box layout to align widgets vertically.

3.2.3: Advanced Usage: Tabs and Tables

from PyQt5.QtWidgets import QApplication, QTabWidget, QWidget, QVBoxLayout, QLabel

app = QApplication([])

tabs = QTabWidget()
tab1 = QWidget()
tab2 = QWidget()
tabs.addTab(tab1, "Tab 1")
tabs.addTab(tab2, "Tab 2")

vbox1 = QVBoxLayout()
vbox1.addWidget(QLabel("Content in Tab 1"))
tab1.setLayout(vbox1)

vbox2 = QVBoxLayout()
vbox2.addWidget(QLabel("Content in Tab 2"))
tab2.setLayout(vbox2)

tabs.show()

app.exec_()

Explanation

  • QTabWidget(): Creates a new tab widget.
  • tabs.addTab(tab1, "Tab 1"): Adds a new tab to the tab widget.

3.2.4: Signal and Slots: Event Handling

from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton

def on_button_click():
    print("Button clicked!")

app = QApplication([])

window = QWidget()
layout = QVBoxLayout()

button = QPushButton("Print Message")
button.clicked.connect(on_button_click)
layout.addWidget(button)

window.setLayout(layout)
window.show()

app.exec_()

Explanation

  • button.clicked.connect(on_button_click): When the button is clicked, the function on_button_click is called, printing a message to the console.

3.2.5: Real-world Example: File Dialog

from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QFileDialog

def open_file_dialog():
    options = QFileDialog.Options()
    file, _ = QFileDialog.getOpenFileName(caption="Open File", options=options)
    if file:
        print(f"Selected file: {file}")

app = QApplication([])

window = QWidget()
layout = QVBoxLayout()

button = QPushButton("Open File Dialog")
button.clicked.connect(open_file_dialog)
layout.addWidget(button)

window.setLayout(layout)
window.show()

app.exec_()

Explanation

  • QFileDialog.getOpenFileName(): Opens a file dialog and returns the selected file.

3.2.6: Tkinter: Building Desktop Applications with Python

Tkinter is Python's standard GUI library and is one of the oldest and most widely-used GUI libraries in Python. It's a thin object-oriented layer on top of the procedural-oriented Tk GUI toolkit.

Tkinter usually comes pre-installed with Python, but if it's not installed, you can get it via your package manager:

sudo apt-get install python3-tk

Basic Usage: Creating a Simple Window

import tkinter as tk

root = tk.Tk()
root.title("Simple Window")
root.mainloop()

Explanation

  • tk.Tk(): Initializes the Tkinter application.
  • root.title("Simple Window"): Sets the title of the window.
  • root.mainloop(): Starts the Tkinter event loop.

3.2.7: Widgets: Label and Button

import tkinter as tk

def on_button_click():
    label.config(text="Hello, Tkinter!")

root = tk.Tk()

button = tk.Button(root, text="Click Me", command=on_button_click)
button.pack()

label = tk.Label(root, text="Hello, World!")
label.pack()

root.mainloop()

Explanation

  • tk.Button(root, text="Click Me", command=on_button_click): Creates a button.
  • label.config(text="Hello, Tkinter!"): Updates the text in the label.

3.2.8: Advanced Usage: Listbox and Entry Widget

import tkinter as tk

def add_item():
    item = entry.get()
    listbox.insert(tk.END, item)

root = tk.Tk()

entry = tk.Entry(root)
entry.pack()

button = tk.Button(root, text="Add Item", command=add_item)
button.pack()

listbox = tk.Listbox(root)
listbox.pack()

root.mainloop()

Explanation

  • tk.Entry(root): Creates an entry widget for text input.
  • tk.Listbox(root): Creates a listbox for displaying list items.

3.2.9: Event Handling: Mouse and Keyboard Events

import tkinter as tk

def on_key(event):
    print(f"Key pressed: {event.char}")

root = tk.Tk()

frame = tk.Frame(root, width=300, height=200)
frame.bind("<Key>", on_key)
frame.pack()
frame.focus_set()

root.mainloop()

Explanation

  • frame.bind("<Key>", on_key): Binds the keypress event to the on_key function.

3.2.10: Real-world Example: File Dialog

import tkinter as tk
from tkinter import filedialog

def open_file_dialog():
    file = filedialog.askopenfilename()
    if file:
        print(f"Selected file: {file}")

root = tk.Tk()

button = tk.Button(root, text="Open File Dialog", command=open_file_dialog)
button.pack()

root.mainloop()

Explanation

  • filedialog.askopenfilename(): Opens a file dialog and returns the selected file path.

 

4. Progress Bars in Web Applications

Implementing progress bars in web applications involves a different set of challenges and solutions compared to desktop applications. Below, we discuss two popular Python web frameworks—Flask and Django—and how you can create a python progress bar in each.

 

4.1 Using Flask with Socket.IO

Socket.IO enables real-time, bidirectional communication between web clients and servers. It can be integrated with Flask to create real-time features like progress bars.

Install the necessary packages:

pip3 install Flask-SocketIO eventlet

Server-side code:

from flask import Flask, render_template
from flask_socketio import SocketIO
import time

app = Flask(__name__)
socketio = SocketIO(app)

@app.route('/')
def index():
    return render_template('index.html')

@socketio.on('request_progress')
def handle_message(message):
    for i in range(101):
        time.sleep(0.1)
        socketio.emit('update_progress', {'percentage': i})

if __name__ == '__main__':
    socketio.run(app)

Client-side HTML with JavaScript:

<!DOCTYPE html>
<html>
<head>
    <title>Python Progress Bar</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
</head>
<body>
    <button onclick="requestProgress()">Start</button>
    <div id="progress-bar" style="width: 0%;">0%</div>

    <script type="text/javascript">
        var socket = io.connect('http://' + document.domain + ':' + location.port);

        function requestProgress() {
            socket.emit('request_progress', {data: 'Start'});
        }

        socket.on('update_progress', function(data) {
            document.getElementById("progress-bar").style.width = data.percentage + "%";
            document.getElementById("progress-bar").innerHTML = data.percentage + "%";
        });
    </script>
</body>
</html>

 

4.2 Using Django Channels

Django Channels extends Django to handle asynchronous protocols like WebSockets, which is essential for creating real-time features like a python progress bar.

Install Django Channels:

pip install channels

In your Django settings.py, add:

INSTALLED_APPS = [
    # ...
    'channels',
]

# Use channels for routing
ASGI_APPLICATION = 'your_project.routing.application'

Create a routing.py in your project folder:

from channels.routing import ProtocolTypeRouter, URLRouter
from django.urls import path
from your_app import consumers

websocket_urlpatterns = [
    path('ws/progress/', consumers.ProgressConsumer.as_asgi()),
]

application = ProtocolTypeRouter({
    'websocket': URLRouter(websocket_urlpatterns),
})

In your Django app folder, create a consumers.py:

import json
import time
import asyncio
from channels.generic.websocket import AsyncWebsocketConsumer

class ProgressConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        await self.accept()

    async def disconnect(self, close_code):
        pass

    async def receive(self, text_data):
        text_data_json = json.loads(text_data)
        for i in range(101):
            await asyncio.sleep(0.1)
            await self.send(text_data=json.dumps({
                'percentage': i
            }))

Client-side JavaScript:

var progressSocket = new WebSocket('ws://' + window.location.host + '/ws/progress/');

progressSocket.onmessage = function(e) {
    var data = JSON.parse(e.data);
    document.getElementById("progress-bar").style.width = data.percentage + "%";
    document.getElementById("progress-bar").innerHTML = data.percentage + "%";
};

In both examples, Flask with Socket.IO and Django Channels, the server pushes updates to the client, allowing for real-time update of the python progress bar.

 

Progress Bars in Multi-threading/Multi-processing Environments

Handling progress bars in multi-threading or multi-processing scenarios can be quite challenging. You need to accurately capture and display the progress of each thread or process, and synchronize them in a way that gives a coherent overall view.

Challenges

  1. Synchronization: Multiple threads or processes could be updating the progress bar simultaneously, which could lead to race conditions.
  2. Accuracy: Accurately capturing the progress of each thread or process can be difficult.
  3. Display: Updating the progress bar in real-time without causing flicker or lag is challenging.

Here are some libraries that you can use to implement a python progress bar in a multi-threading or multi-processing environment:

 

1. Using tqdm

tqdm is a fast and extensible progress bar library that supports parallel processing.

from tqdm import tqdm
from concurrent.futures import ThreadPoolExecutor
import time

def task(n):
    time.sleep(n)
    return n

with ThreadPoolExecutor() as executor:
    futures = [executor.submit(task, n) for n in range(1, 6)]
    for future in tqdm(futures, desc="Processing", total=len(futures)):
        future.result()

 

2. Using alive-progress

alive-progress is another python progress bar library that has multi-threading support. It produces animated and beautiful progress bars.

from alive_progress import alive_bar
from concurrent.futures import ThreadPoolExecutor
import time

def task(n):
    time.sleep(n)
    return n

with alive_bar(5, title="Processing") as bar:
    with ThreadPoolExecutor() as executor:
        futures = [executor.submit(task, n) for n in range(1, 6)]
        for future in futures:
            future.result()
            bar()

How these Libraries Support Parallelism

  1. Thread-Safety: Both tqdm and alive-progress are designed to be thread-safe, so you can use them in multi-threaded environments without worrying about synchronization issues.
  2. Atomic Updates: These libraries ensure that updates to the progress bar are atomic, so you don't see any flicker or partial updates.
  3. Batch Updates: You can choose to update the progress bar after a batch of tasks is complete, rather than after each individual task, to minimize performance overhead.

 

Comparison Table of Different Libraries

Below is a comparison table of different libraries for creating a python progress bar. The table aims to highlight key aspects, such as ease of use, customization, and suitability for various environments (like multi-threading or web applications).

Features / Libraries tqdm progressbar2 alive-progress PySimpleGUI Flask with Socket.IO Django Channels
Ease of Use High High High Moderate Moderate Moderate
Customization High High High High High High
Installation Easy Easy Easy Easy Moderate Moderate
Multi-threading Support Yes Yes Yes No No No
Web App Support No No No No Yes Yes
Animation Yes Yes Yes Yes Yes Yes
Documentation High High High High High High
Dependencies Low Low Low Low Moderate Moderate

Key Takeaways

  • Ease of Use: tqdm, progressbar2, and alive-progress are particularly easy for quick setup, making them a good fit for both beginners and experts.
  • Customization: All listed libraries offer a good level of customization. PySimpleGUI, Flask with Socket.IO, and Django Channels provide a higher level of customization but come with a steeper learning curve.
  • Multi-threading Support: tqdm, progressbar2, and alive-progress are designed to support multi-threading environments.
  • Web App Support: For web applications, Flask with Socket.IO and Django Channels are the way to go, but they don't inherently support multi-threading for the progress bars.
  • Animation: All libraries offer some level of animation to make the python progress bar visually appealing.
  • Documentation: High-quality documentation is available for all libraries, making it easier to dive deeper and exploit advanced features.

 

Frequently Asked Questions

What is a Python Progress Bar?

A Python progress bar is a visual indicator that shows the status of a long-running task. It provides a graphical representation of a task's current state versus its complete state. Libraries like tqdm, progressbar2, and alive-progress can be used to easily implement progress bars in Python.

How Can I Add a Progress Bar in Python Console Applications?

You can use libraries like tqdm, progressbar2, or alive-progress. These libraries offer a straightforward API for adding a python progress bar to your console-based applications.

Are There Python Progress Bar Libraries That Support Multi-Threading?

Yes, libraries such as tqdm, progressbar2, and alive-progress offer thread-safe progress bars, allowing you to implement progress tracking in multi-threaded applications.

Can I Use Python Progress Bars in Web Applications?

Certainly. You can use technologies like Flask with Socket.IO or Django Channels to create real-time progress bars in web applications. These allow you to push updates from the server to the client for a more interactive user experience.

How Do I Customize the Look of My Python Progress Bar?

Libraries like PySimpleGUI, tqdm, and alive-progress offer extensive customization options. You can change the style, colors, and format to make your python progress bar visually appealing.

Do I Need to Install Additional Packages for Web-Based Python Progress Bars?

Yes, you would typically need to install Flask and Socket.IO for Flask-based web applications or Django and Django Channels for Django-based web applications to create a python progress bar.

Are Python Progress Bars Cross-Platform?

Most Python progress bar libraries are cross-platform and will work on Windows, macOS, and Linux. However, the implementation might vary slightly, especially for GUI-based progress bars.

Can I Create Animated Python Progress Bars?

Yes, libraries like alive-progress specialize in creating animated progress bars. You can also use PySimpleGUI for GUI-based animated progress bars.

How Do I Update a Progress Bar in Real-Time?

Real-time updates in a python progress bar can be achieved using loops in console-based applications. For web applications, real-time updates are commonly done using WebSockets with Flask and Socket.IO or Django Channels.

What Should I Do If My Python Progress Bar Isn’t Updating?

Make sure you are correctly updating the progress state in your code. If you're using a console-based progress bar, you may also need to flush the standard output using sys.stdout.flush() for real-time updates.

 

Summary

Progress bars are indispensable tools for enhancing user experience in both console and web applications. They provide real-time feedback on the status of long-running tasks, improving user engagement and satisfaction. Python offers a range of libraries and frameworks, from tqdm and progressbar2 for console applications to Flask with Socket.IO and Django Channels for web-based applications, making it easier than ever to implement a python progress bar. Each comes with its own set of features, advantages, and levels of customization, allowing developers to choose the best fit for their specific needs.

  • For console-based applications, tqdm, progressbar2, and alive-progress are top choices offering ease of use, customization, and multi-threading support.
  • For GUI applications, PySimpleGUI offers a flexible, though slightly more complex, approach to implementing progress bars.
  • Web-based python progress bars can be implemented using Flask with Socket.IO or Django Channels, offering real-time updates and a high degree of customization.

 

Additional Resources

  1. tqdm: Official Documentation
  2. progressbar2: Official Documentation
  3. alive-progress: GitHub Repository
  4. PySimpleGUI: Official Docs
  5. Flask with Socket.IO: Flask-SocketIO Documentation
  6. Django Channels: Official Documentation

 

Deepak Prasad

Deepak Prasad

He is the founder of GoLinuxCloud and brings over a decade of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels in various domains, from development to DevOps, Networking, and Security, ensuring robust and efficient solutions for diverse projects. You can connect with him on his LinkedIn profile.

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to admin@golinuxcloud.com

Thank You for your support!!

Leave a Comment