0

Possible Duplicate:
Replace console output in python

I am trying to write a program that outputs information including updates to the command line. What I mean by updates is, for example, if files are being processed by the program, perhaps it will keep an updated count of the files processed so far. So 1 file is replaced with 2 files and then with 3 files and so forth.

The following is a sample piece of code that counts out some files and then displays a loading bar:

#!/bin/bash

for a in {1..10}
do
    echo -ne " $a files processed.\r"
    sleep 1
done
echo ""
echo -ne '#####                     (33%)\r'
sleep 1
echo -ne '#############             (66%)\r'
sleep 1
echo -ne '#######################   (100%)\r'
echo -ne '\n'

Basically, the command line output gets periodically overwritten giving the effect of a primitive text-based animation in the terminal.

There are two problems here:

  1. From what I know from doctors, the echo command is not portable at all.
  2. I want to do this in a python program, not with a bash file.

Is there a way to achieve functionality similar to this using python?

Community
  • 1
  • 1
jbranchaud
  • 5,909
  • 9
  • 45
  • 70

1 Answers1

2

An equivalent implementation in Python would be this:

import sys, time

for a in range(1,11):
    sys.stdout.write('\r {0} files processed.'.format(a))
    time.sleep(1)

print('')
sys.stdout.write('\r#####                     (33%)')
time.sleep(1)
sys.stdout.write('\r#############             (66%)')
time.sleep(1)
sys.stdout.write('\r#######################   (100%)')
print('')

You need to use sys.stdout.write as print by default adds a new-line. If you are using the print-function (Python 3, or by explicitely importing it in Python 2), you can also use print('text', end=''). Alternatively in Python 2, you can use the print-statement’s feature to suppress the line termination like this: print 'text',

poke
  • 369,085
  • 72
  • 557
  • 602
  • Or you can do `print "x",` for no new line – Eric Nov 03 '12 at 17:36
  • In python2.x, you can also suppress the newline by `print "string",` (note the trailing comma) – mgilson Nov 03 '12 at 17:36
  • What is it about the `\r` that causes the text to display this way? – jbranchaud Nov 03 '12 at 17:36
  • @Eric My code is compatible for both Python 2 and 3 though. But I’m going to add that note for Python 2. – poke Nov 03 '12 at 17:37
  • @Treebranch -- '\r' is "carriage return" -- which means "go back to the beginning of the line" in most terminals/shells. – mgilson Nov 03 '12 at 17:38
  • @Treebranch The `\r` is a [carriage return](http://en.wikipedia.org/wiki/Carriage_return) that basically tells the console to return to the first character without advancing to the next line. So whatever you print afterwards will overwrite whatever was written in the line before. – poke Nov 03 '12 at 17:39
  • @poke: You shouldn't drop the print statement entirely for compatibility with 2 and 3. That's just silly. – Eric Nov 03 '12 at 17:40
  • @Eric There is no print statement in Python 3. – poke Nov 03 '12 at 17:40
  • @poke: And there's no print function in python2. That doesn't mean you should aim to write code that never uses either. – Eric Nov 03 '12 at 17:41
  • @Eric Unless a question is exclusively about either Py2 or Py3, I’ll try to only post code that works on both. And I think my explanation after the code is clear enough that you can write it differently too. – poke Nov 03 '12 at 17:44
  • @poke: You've failed to write code that works on both anyway: `print()` prints a literal `()` on python 2. – Eric Nov 03 '12 at 17:46
  • @mgilson That will suppress the newline, but any following `print` still has the side-effect of having an unwanted ` ` though.. – Jon Clements Nov 03 '12 at 17:47
  • Does this code actually work using `sys.stdout.write` (I admit I haven't checked it)... If sys.stdout is buffered, then this might have the effect of never printing anything. – Jon Clements Nov 03 '12 at 17:48
  • @Eric You’re right, missed that in my test; fixed. – poke Nov 03 '12 at 17:49
  • 1
    @JonClements In case the console buffers too much, you can add a `sys.stdout.flush()` after each write. Note that you would have to do this even if you used print without a line ending. So using print won’t save you from importing `sys` and accessing the output at a lower lever if that’s everyone’s problem. – poke Nov 03 '12 at 17:51
  • @poke I'm not saying it's a problem - just that it's something the OP may need to be aware of if using this answer – Jon Clements Nov 03 '12 at 17:52
  • It's a good idea to add `sys.stdout.flush()` after the write. Otherwise, when writing to line-buffered devices, such as a TTY, the text can remain in a stdio buffer indefinitely. (`echo` doesn't have this problem because it exits immediately after printing, which automatically flushes its stdio buffers.) – user4815162342 Nov 03 '12 at 19:04