Write a responsive progressbar for the commandline using Python

Deepjyoti Barman @deepjyoti30
Nov 17, 2019 12:00 AM UTC
Post cover

“Everyday life is like programming, I guess. If you love something you can put beauty into it.”

We have all seen progressbars everywhere. We see them on websites all the time and those of us who use a Linux distro, looking at a progressbar is like one of our day to day tasks. Especially when you use the terminal like you can nuke a country from it. Progressbars are used by a lot of commandline software's we use. Python's pip use them, npm has an awesome progressbar along with a spinner and our holy pacman, obviously has one too.

However, progressbars are sometimes messy. If you've used pip more than just a couple of times, it is unavoidable to notice that the progressbar's size is predefined. What that means is, the bar doesn't resize depending on the width of the terminal, messing up the output a lot of times.

Though, pip's bar might not be responsive, pacman has a really neat bar that hardly screw's up. The length of the bar changes according to the width of the terminal.

So how can we make a responsive, awesome progressbar ourselves? Read ahead and you'll know.

Things to know beforehand.

So we need to know first how a bar is actually printed. As we all know, printing a line in the terminal is not big deal, especially with languages like Python. When we print a line, it's printed and goes to the next line (in python), but we want to progressively update the same line if we want to print the bar.

In this case, we can use \r. It is the carriage return escape sequence which makes sure that we are able to wipe the current line. So what we will do is keep wiping the line and printing every after a while (this just means we can add a gap between printing by using a time library, makes things a bit more efficient). So that we can print a bar pretty easily.

We are going to use the sys module to do the above mentioned things. So we will keep repeating 3 lines in order to make sure our bar keeps getting updated.

We need to put it in a loop to make sure that the bar is printed to 100%, after it gets to 100% we can simply break the loop.

Making the bar.

Now that we know how to print the bar, let's make the bar. We can make a simple repeating the below steps on loop.

So the things we will have to do are

  • Determine the percentage done and percentage left
  • Print # number of done, i:e multiply and print (space) number of left.
  • Sleep for a while, check the progress and print again.
  • Keep repeating untill we reach 100%

The above code will print a bar of of 20 # after it's done.

Making it responsive.

Now that we have our bar in place, we want to make sure that it respects the width of the terminal window and changes it's length according to it. We can get the width using the os module's popen function.

After we get the width, we will use it every time before printing the bar. This way, even if we resize the window while the bar is increasing, it will resize itself automatically.

In the above code, we get the width of the terminal, use a loop to decrease the length of the bar from 40 to 20 to 10 and so on. The length is decreased by half each time.

After that we use the length to determine how much of the bar we need to show as done by using the formula percent / 100 / bar_len. Here bar_len plays an important role since the amount of bar to be filled is directly related to the length of the bar.

So, if our bar is of 40 length, then in each percentage increase, the bar will be calculated using percent / (100/ 40) = percent / 2.5.

So that is how we can make a responsive progressbar for the commandline. In case you want to dive deeper and make your bar better, check my GitHub repo of a downloader where I'm using the same concept to create a progressbar. You can make it so much better, like adding colors, adding other stats regarding the progress like the speed, percentage etc.

Check the repo here.

Discussion