Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Text Progress Bar in the Console [closed]

I wrote a simple console app to upload and download files from an FTP server using the ftplib.

I would like the app to show some visualization of its download/upload progress for the user; each time a data chunk is downloaded, I would like it to provide a progress update, even if it's just a numeric representation like a percentage.

Importantly, I want to avoid erasing all the text that's been printed to the console in previous lines (i.e. I don't want to "clear" the entire terminal while printing the updated progress).

This seems a fairly common task – how can I go about making a progress bar or similar visualization that outputs to my console while preserving prior program output?

like image 515
bobber205 Avatar asked Jul 04 '10 00:07

bobber205


People also ask

Which bar displays the progress bar?

In this example, modeless progress is shown in the address bar. Otherwise, if the window has a status bar, display the modeless progress in the status bar. Put any corresponding text to its left in the status bar. In this example, modeless progress is shown in the status bar.

How do I use the progress bar in tkinter?

Use the ttk. Progressbar(container, orient, length, mode) to create a progressbar. Use the indeterminate mode when the program cannot accurately know the relative progress to display. Use the determinate mode if you know how to measure the progress accurately.


1 Answers

Python 3

A Simple, Customizable Progress Bar

Here's an aggregate of many of the answers below that I use regularly (no imports required).

Note: All code in this answer was created for Python 3; see end of answer to use this code with Python 2.

# Print iterations progress def printProgressBar (iteration, total, prefix = '', suffix = '', decimals = 1, length = 100, fill = '█', printEnd = "\r"):     """     Call in a loop to create terminal progress bar     @params:         iteration   - Required  : current iteration (Int)         total       - Required  : total iterations (Int)         prefix      - Optional  : prefix string (Str)         suffix      - Optional  : suffix string (Str)         decimals    - Optional  : positive number of decimals in percent complete (Int)         length      - Optional  : character length of bar (Int)         fill        - Optional  : bar fill character (Str)         printEnd    - Optional  : end character (e.g. "\r", "\r\n") (Str)     """     percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))     filledLength = int(length * iteration // total)     bar = fill * filledLength + '-' * (length - filledLength)     print(f'\r{prefix} |{bar}| {percent}% {suffix}', end = printEnd)     # Print New Line on Complete     if iteration == total:          print() 

Sample Usage

import time  # A List of Items items = list(range(0, 57)) l = len(items)  # Initial call to print 0% progress printProgressBar(0, l, prefix = 'Progress:', suffix = 'Complete', length = 50) for i, item in enumerate(items):     # Do stuff...     time.sleep(0.1)     # Update Progress Bar     printProgressBar(i + 1, l, prefix = 'Progress:', suffix = 'Complete', length = 50) 

Sample Output

Progress: |█████████████████████████████████████████████-----| 90.0% Complete 

Update

There was discussion in the comments regarding an option that allows the progress bar to adjust dynamically to the terminal window width. While I don't recommend this, here's a gist that implements this feature (and notes the caveats).

Single-Call Version of The Above

A comment below referenced a nice answer posted in response to a similar question. I liked the ease of use it demonstrated and wrote a similar one, but opted to leave out the import of the sys module while adding in some of the features of the original printProgressBar function above.

Some benefits of this approach over the original function above include the elimination of an initial call to the function to print the progress bar at 0% and the use of enumerate becoming optional (i.e. it is no longer explicitly required to make the function work).

def progressBar(iterable, prefix = '', suffix = '', decimals = 1, length = 100, fill = '█', printEnd = "\r"):     """     Call in a loop to create terminal progress bar     @params:         iterable    - Required  : iterable object (Iterable)         prefix      - Optional  : prefix string (Str)         suffix      - Optional  : suffix string (Str)         decimals    - Optional  : positive number of decimals in percent complete (Int)         length      - Optional  : character length of bar (Int)         fill        - Optional  : bar fill character (Str)         printEnd    - Optional  : end character (e.g. "\r", "\r\n") (Str)     """     total = len(iterable)     # Progress Bar Printing Function     def printProgressBar (iteration):         percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))         filledLength = int(length * iteration // total)         bar = fill * filledLength + '-' * (length - filledLength)         print(f'\r{prefix} |{bar}| {percent}% {suffix}', end = printEnd)     # Initial Call     printProgressBar(0)     # Update Progress Bar     for i, item in enumerate(iterable):         yield item         printProgressBar(i + 1)     # Print New Line on Complete     print() 

Sample Usage

import time  # A List of Items items = list(range(0, 57))  # A Nicer, Single-Call Usage for item in progressBar(items, prefix = 'Progress:', suffix = 'Complete', length = 50):     # Do stuff...     time.sleep(0.1) 

Sample Output

Progress: |█████████████████████████████████████████████-----| 90.0% Complete 

Python 2

To use the above functions in Python 2, set the encoding to UTF-8 at the top of your script:

# -*- coding: utf-8 -*- 

And replace the Python 3 string formatting in this line:

print(f'\r{prefix} |{bar}| {percent}% {suffix}', end = printEnd) 

With Python 2 string formatting:

print('\r%s |%s| %s%% %s' % (prefix, bar, percent, suffix), end = printEnd) 
like image 62
Greenstick Avatar answered Sep 17 '22 08:09

Greenstick