A progress bar is a visual element that shows how much of a task has been completed. Progress bars are often used alongside downloading files or software installations. This project creates a getProgressBar() function that returns a progress bar string based on the arguments passed to it. It simulates a downloading file, but you can reuse the progress bar code in your own projects.
The Program in Action
When you run progressbar.py, the output will look like this:
Progress Bar Simulation, by Al Sweigart
[█████████ ] 24.6% 1007/4098
How It Works
The progress bar relies on a certain trick that programs running in terminal windows can perform. Just as '\n' and '\t' are escape characters for newline and tab characters, respectively, '\b' is an escape character for backspace characters. If you “print” a backspace character, the text cursor will move to the left and erase the previously printed character. This only works for the current line the text cursor is on. If you run the code print('Hello\b\b\b\b\bHowdy'), Python will print the text “Hello,” move the text cursor back five spaces, and then print the text “Howdy.” The “Howdy” text will overwrite “Hello,” making it look as though you called “Howdy.”
We can use this technique to create an animated progress bar on a single line by printing one version of the bar, moving the text cursor back to the start, then printing an updated progress bar. This effect can generate any text animation without requiring a module such as bext, though it will be limited to taking up a single line in the terminal window.
Once you’ve created this program, you can display progress bars in your other Python programs by running import progressbar and printing the string returned from progressbar.getProgressBar().
1. """Progress Bar Simulation, by Al Sweigart [email protected]
2. A sample progress bar animation that can be used in other programs.
3. View this code at https://nostarch.com/big-book-small-python-projects
4. Tags: tiny, module"""
6. import random, time
8. BAR = chr(9608) # Character 9608 is '█'
10. def main():
11. # Simulate a download:
12. print('Progress Bar Simulation, by Al Sweigart')
13. bytesDownloaded = 0
14. downloadSize = 4096
15. while bytesDownloaded < downloadSize:
16. # "Download" a random amount of "bytes":
17. bytesDownloaded += random.randint(0, 100)
19. # Get the progress bar string for this amount of progress:
20. barStr = getProgressBar(bytesDownloaded, downloadSize)
22. # Don't print a newline at the end, and immediately flush the
23. # printed string to the screen:
24. print(barStr, end='', flush=True)
26. time.sleep(0.2) # Pause for a little bit:
28. # Print backspaces to move the text cursor to the line's start:
29. print('\b' * len(barStr), end='', flush=True)
32. def getProgressBar(progress, total, barWidth=40):
33. """Returns a string that represents a progress bar that has barWidth
34. bars and has progressed progress amount out of a total amount."""
36. progressBar = '' # The progress bar will be a string value.
37. progressBar += '[' # Create the left end of the progress bar.
39. # Make sure that the amount of progress is between 0 and total:
40. if progress > total:
41. progress = total
42. if progress < 0:
43. progress = 0
45. # Calculate the number of "bars" to display:
46. numberOfBars = int((progress / total) * barWidth)
48. progressBar += BAR * numberOfBars # Add the progress bar.
49. progressBar += ' ' * (barWidth - numberOfBars) # Add empty space.
50. progressBar += ']' # Add the right end of the progress bar.
52. # Calculate the percentage complete:
53. percentComplete = round(progress / total * 100, 1)
54. progressBar += ' ' + str(percentComplete) + '%' # Add percentage.
56. # Add the numbers:
57. progressBar += ' ' + str(progress) + '/' + str(total)
59. return progressBar # Return the progress bar string.
62. # If the program is run (instead of imported), run the game:
63. if __name__ == '__main__':
After entering the source code and running it a few times, try making experimental changes to it. On your own, you can also try to figure out how to do the following:
Create a one-line animation of a spinner that alternates between the characters |, /, -, and \ to produce a rotating effect.
Create a program that can display a scrolling marquee of text moving from left to right.
Create a one-line animation that displays a set of four equal signs moving back and forth as a single unit, similar to the red scanning light on the robot car from the TV show Knight Rider or the Cylon robot face from the TV show Battlestar Galactica.
Exploring the Program
Try to find the answers to the following questions. Experiment with some modifications to the code and rerun the program to see what effect the changes have.
What happens if you delete or comment out print('\b' * len(barStr), end='', flush=True) on line 29?
What happens if you switch the order of lines 48 and 49?
What happens if you change round(progress / total * 100, 1) on line 53 to round(progress / total * 100)?