views:

270

answers:

7

Is there a good way to do the following?

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

Each time some data chunks are downloaded, I want to update a text progress bar, even if it's just a number.

But I don't want to erase all the text that's been printed to the console. (Doing a "clear" and then printing the updated percentage.)

Thanks for any suggestions. New to python so even less of a clue on what to do. :P

+3  A: 

Write a \r to the console. That is a "carriage return" which causes all text after it to be echoed at the beginning of the line. Something like:

def update_progress(progress):
    print '\r[{0}] {1}%'.format('#'*(progress/10), progress)

which will give you something like: [ ########## ] 100%

Aviral Dasgupta
Do '\r' + myPercentage printout?
bobber205
Do `\r` and then write the whole line out again. Basically: `print("\rProgress: [{0:50s}] {1:.1f}%".format('#' * int(amtDone * 50), amtDone * 100))`, where `amtDone` is a float between 0 and 1.
Mike DeSimone
+3  A: 

Here's a nice example of a progressbar written in Python: http://nadiana.com/animated-terminal-progress-bar-in-python

But if you want to write it yourself. You could use the curses module to make things easier :)

[edit] Perhaps easier is not the word for curses. But if you want to create a full-blown cui than curses takes care of a lot of stuff for you.

WoLpH
`curses`? Easier? Hmmm....
Aviral Dasgupta
An excellent article, I was going to give a link to it but couldn't find in my bookmarks :)
Andy Mikhaylenko
@Aviral Dasgupta: fair enough, easier might not be the right word here. It can save you a lot of work though, but it really depends on what you're looking for.
WoLpH
Not looking for anything near this involved, but thanks anyway. :)
bobber205
+5  A: 

Writing '\r' will move the cursor back to the beginning of the line.

This displays a percentage counter:

>>> for i in range(100):
...    time.sleep(1)
...    sys.stdout.write("\r%d%%" %i)    # or print >> sys.stdout, "\r%d%%" %i,
...    sys.stdout.flush()
... 
Stephen
Pasted that and ran. It prints to a new line each time. I want the number to be updated on the same line. :)
bobber205
Stephen
I am using python 2.6I tried in Aptana studio and on the command line. Prints on multiple lines. :(
bobber205
@bobber205 : Edited, try `sys.stdout.write`
Stephen
Some proof. :)http://twitpic.com/227xk2
bobber205
Replaced 3rd line with yours. Same problem as the picture illustrates.
bobber205
Hmm, proof proven :) I suspect that the "Aptana studio" doesn't support `\r`. I'm not familiar with Aptana, so I'm not sure what to tell you :(
Stephen
I get the exact same results in "cmd" on Windows 7. Oh well. :P
bobber205
`\r` only works on unix (and even then, not necessarily in all shells). On windows you need to use the `home` key, which SHOULD be `\x00\x71`, but I didn't test it.
Nick Bastin
@Nick `\r` works on all platforms.
Aviral Dasgupta
@Aviral: It most certainly does not perform a traditional carriage return in powershell - it's not a *platform* thing, per se, it has to do with how your controlling shell treats control sequences (The POSIX shell definition doesn't actually require that carriage return reset the character position to the beginning of the line either).
Nick Bastin
+1  A: 

Run this at the Python command line (not in any IDE or development environment):

>>> import threading
>>> for i in range(50+1):
...   threading._sleep(0.5)
...   print "\r%3d" % i, ('='*i)+('-'*(50-i)),

Works fine on my Windows system.

Paul McGuire
A: 
import sys
def progresssbar():
         for i in range(100):
            time.sleep(1)
            sys.stdout.write("%i\r" % i)

progressbar()

If the code is not in the function then stdout prints the data and the length of the data.Don't know why stdout doesn't in a function.

A: 

I am using this one from reddit I like it because it can print progress for every item in one line, and it shouldn't erase printouts from program.

Ib33X