Replace console output in Python

2019-01-01 09:08发布

问题:

I\'m wondering how I could create one of those nifty console counters in Python as in certain C/C++-programs.

I\'ve got a loop doing things and the current output is along the lines of:

Doing thing 0
Doing thing 1
Doing thing 2
...

what would be neater would be to just have the last line update;

X things done.

I\'ve seen this in a number of console programs and am wondering if/how I\'d do this in Python.

回答1:

An easy solution is just writing \"\\r\" before the string and not adding a newline; if the string never gets shorter this is sufficient...

sys.stdout.write(\"\\rDoing thing %i\" % i)
sys.stdout.flush()

Slightly more sophisticated is a progress bar... this is something I am using:

def startProgress(title):
    global progress_x
    sys.stdout.write(title + \": [\" + \"-\"*40 + \"]\" + chr(8)*41)
    sys.stdout.flush()
    progress_x = 0

def progress(x):
    global progress_x
    x = int(x * 40 // 100)
    sys.stdout.write(\"#\" * (x - progress_x))
    sys.stdout.flush()
    progress_x = x

def endProgress():
    sys.stdout.write(\"#\" * (40 - progress_x) + \"]\\n\")
    sys.stdout.flush()

You call startProgress passing the description of the operation, then progress(x) where x is the percentage and finally endProgress()



回答2:

A more elegant solution could be:

def progressBar(value, endvalue, bar_length=20):

        percent = float(value) / endvalue
        arrow = \'-\' * int(round(percent * bar_length)-1) + \'>\'
        spaces = \' \' * (bar_length - len(arrow))

        sys.stdout.write(\"\\rPercent: [{0}] {1}%\".format(arrow + spaces, int(round(percent * 100))))
        sys.stdout.flush()

call this function with value and endvalue, result should be

Percent: [------------->      ] 69%


回答3:

The other answer may be better, but here\'s what I was doing. First, I made a function called progress which prints off the backspace character:

def progress(x):
    out = \'%s things done\' % x  # The output
    bs = \'\\b\' * 1000            # The backspace
    print bs,
    print out,

Then I called it in a loop in my main function like so:

def main():
    for x in range(20):
        progress(x)
    return

This will of course erase the entire line, but you can mess with it to do exactly what you want. I ended up make a progress bar using this method.



回答4:

For anyone who stumbles upon this years later (like I did), I tweaked 6502\'s methods a little bit to allow the progress bar to decrease as well as increase. Useful in slightly more cases. Thanks 6502 for a great tool!

Basically, the only difference is that the whole line of #s and -s is written each time progress(x) is called, and the cursor is always returned to the start of the bar.

def startprogress(title):
    \"\"\"Creates a progress bar 40 chars long on the console
    and moves cursor back to beginning with BS character\"\"\"
    global progress_x
    sys.stdout.write(title + \": [\" + \"-\" * 40 + \"]\" + chr(8) * 41)
    sys.stdout.flush()
    progress_x = 0


def progress(x):
    \"\"\"Sets progress bar to a certain percentage x.
    Progress is given as whole percentage, i.e. 50% done
    is given by x = 50\"\"\"
    global progress_x
    x = int(x * 40 // 100)                      
    sys.stdout.write(\"#\" * x + \"-\" * (40 - x) + \"]\" + chr(8) * 41)
    sys.stdout.flush()
    progress_x = x


def endprogress():
    \"\"\"End of progress bar;
    Write full bar, then move to next line\"\"\"
    sys.stdout.write(\"#\" * 40 + \"]\\n\")
    sys.stdout.flush()


回答5:

If I understood well (not sure) you want to print using <CR> and not <LR>?

If so this is possible, as long the console terminal allows this (it will break when output si redirected to a file).

from __future__ import print_function
print(\"count x\\r\", file=sys.stdout, end=\" \")


回答6:

In python 3 you can do this to print on the same line:

print(\'\', end=\'\\r\')

Especially useful to keep track of the latest update and progress.

I would also recommend tqdm from here if one wants to see the progress of a loop. It prints the current iteration and total iterations as a progression bar with an expected time of finishing. Super useful and quick. Works for python2 and python3.



回答7:

Added a little bit more functionality to the example of Aravind Voggu:

def progressBar(name, value, endvalue, bar_length = 50, width = 20):

        percent = float(value) / endvalue

        arrow = \'-\' * int(round(percent*bar_length) - 1) + \'>\'

        spaces = \' \' * (bar_length - len(arrow))

        sys.stdout.write(\"\\r{0: <{1}} : [{2}]{3}%\".format(\\
                         name, width, arrow + spaces, int(round(percent*100))))

        sys.stdout.flush()

        if value == endvalue:        

             sys.stdout.write(\'\\n\\n\')

Now you are able to generate multiple progressbars without replacing the once before.
I´ve also added name as a value with a fixed width.

For two loops and two times the use of progressBar() the result will look like:


\"enter



标签: python