1

I'm currenty working on a progress bar for another project. I pretty much have everything done and working as intended.

However, i am having an issue, where i can't have two (or more) bars displaying simultaneously. The second one always seems to overwrite the first.

Here's the code (excuse my crappy coding skills):

Progress Bar Class:

import sys


class ProgressBar():

    full_size = 100
    standard = 50
    small = 25

    def __init__(self, pretext, length=50, total=100):
        self.pretext = pretext
        self.length = length
        self.total = total

    def update_bar(self, fill_amount):

        real_fill_amount = int(self.length * fill_amount / self.total)

        sys.stdout.write("\r%s |%s%s| %s" % (self.pretext,
                                             "█" * real_fill_amount,
                                             "░" * (self.length - real_fill_amount),
                                             str(fill_amount) + "%"))
        sys.stdout.flush()

Example code (CPU and Memory Usage Meter):

from pout_progressbar import ProgressBar
import psutil
import time

bar1 = ProgressBar("CPU Usage", length=ProgressBar.standard, total=100)
bar2 = ProgressBar("Memory Usage", length=ProgressBar.standard, total=100)

while True:
    bar1.update_bar(int(psutil.cpu_percent(interval=1)))
    bar2.update_bar(int(psutil.virtual_memory().percent))
    time.sleep(0.5)

Note: pout_progressbar is the filename of the ProgressBar module.

In the example script, two bars are supposed to be showing, but only the second one is showing.

Is there any way i can fix this ?

Thanks in advance.

Cubemation
  • 37
  • 1
  • 9

2 Answers2

1

That is because your second progress bar output overwrites that of the first. Here is a way to fix that:

import sys
import psutil
import time


class ProgressBar:
    full_size = 100
    standard = 50
    small = 25

    def __init__(self, pretext, length=50, total=100):
        self.pretext = pretext
        self.length = length
        self.total = total

    def update_bar(self, fill_amount):
        real_fill_amount = self.length * fill_amount // self.total
        progress = f"{self.pretext} |{'█'*real_fill_amount}" \
                   f"{'░'*(self.length - real_fill_amount)}| {fill_amount}%"
        return progress


bar1 = ProgressBar("CPU Usage")
bar2 = ProgressBar("Memory Usage")

while True:
    progress1 = bar1.update_bar(int(psutil.cpu_percent(interval=1)))
    progress2 = bar2.update_bar(int(psutil.virtual_memory().percent))

    sys.stdout.write(f'\r{progress1}\t{progress2}')
    sys.stdout.flush()
    time.sleep(0.5)

However, there is another problem. It is not trivial to overwrite more than just the previous line. So for now, both progess bars are displayed in the same line. If that is not ok for you, you need to look into one of the options to overwrite multiple lines, however how to do that is system dependent.

mapf
  • 1,906
  • 1
  • 14
  • 40
0

As output of next bar depends on previous one, separating these is not able. So if I write:

class ProgressBars():

    full_size = 100
    standard = 50
    small = 25

    def __init__(self, pretexts, length=50, total=100):
        self.pretexts = pretexts
        self.length = length
        self.total = total

    def update_bar(self, fill_amounts):

        real_fill_amounts = [int(self.length * x / self.total) for x in fill_amounts]

        line = "%s |%s%s| %s" % (self.pretext,
                                             "█" * real_fill_amount,
                                             "░" * (self.length - real_fill_amount))
                                             str(fill_amount) + "%"))
        sys.stdout.write("\b" * (len(line) + len(fill_amounts))
        sys.stdout.write(line)
        sys.stdout.flush()

If you wan to control console in advance, There is curses.

Akihito KIRISAKI
  • 1,243
  • 6
  • 12