44

Most of questions related to this topics here in SO is as follows:

How to print some information on the same line without introducing a new line

Q1 Q2.

Instead, my question is as follows:

I expect to see the following effect,

>> You have finished 10%

where the 10 keep increasing in the same time. I know how to do this in C++ but cannot find a good solution in python.

Community
  • 1
  • 1
q0987
  • 34,938
  • 69
  • 242
  • 387
  • 1
    Can you output ASCII character 8 (a backspace) to delete the 10, then write out a new value? – Mike Christensen Oct 10 '11 at 16:09
  • Nice. Not sure that you need the `'\r'` at the beginning? This also works in Python 2, and may facilitate easier mapping from 2 to 3 in future: `print '>> You have finished %d%%' % i, '\r',` – mike Jul 15 '15 at 00:05

6 Answers6

40
import sys, time

for i in xrange(0, 101, 10):
  print '\r>> You have finished %d%%' % i,
  sys.stdout.flush()
  time.sleep(2)
print

The \r is the carriage return. You need the comma at the end of the print statement to avoid automatic newline. Finally sys.stdout.flush() is needed to flush the buffer out to stdout.

For Python 3, you can use:

print("\r>> You have finished {}%".format(i), end='')
fnunnari
  • 159
  • 2
  • 11
NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • 1
    And now, in "more-modern" Python 3: print (f"\r>> You have finished {i}%", end='', flush=True) – NoCake Sep 21 '20 at 17:49
36

Python 3

You can use keyword arguments to print:

print('string', end='\r', flush=True)

  • end='\r' replaces the default end-of-line behavior with '\r'
  • flush=True flushes the buffer, making the printed text appear immediately.

Python 2

In 2.6+ you can use from __future__ import print_function at the start of the script to enable Python 3 behavior. Or use the old way:

Python's print puts a newline after each command, unless you suppress it with a trailing comma. So, the print command is:

print 'You have finished {0}%\r'.format(percentage),

Note the comma at the end.

Unfortunately, Python only sends the output to the terminal after a complete line. The above is not a complete line, so you need to flush it manually:

import sys
sys.stdout.flush()
Petr Viktorin
  • 65,510
  • 9
  • 81
  • 81
  • is there a solution that is compatible for both python 2 and 3? The python 2 version but with enclosing ( ) for python 3 prints a new line on the latter version. – fjleon Mar 27 '18 at 21:11
  • @fjleon, yes! Use a `__future__` import. I edited the answer to make it a bit more modern :) – Petr Viktorin Mar 30 '18 at 19:41
  • I actually found a solution that doesn't require the future import and posted it way below – fjleon Mar 31 '18 at 20:24
4

On linux( and probably on windows) you can use curses module like this

import time
import curses

win = curses.initscr()
for i in range(100):
    win.clear()
    win.addstr("You have finished %d%%"%i)
    win.refresh()
    time.sleep(.1)
curses.endwin()

Benfit with curses as apposed to other simpler technique is that, you can draw on terminal like a graphics program, because curses provides moving to any x,y position e.g. below is a simple script which updates four views

import time
import curses

curses.initscr()

rows = 10
cols= 30
winlist = []
for r in range(2):
    for c in range(2):
        win = curses.newwin(rows, cols, r*rows, c*cols)
        win.clear()
        win.border()
        winlist.append(win)

for i in range(100):
    for win in winlist:
        win.addstr(5,5,"You have finished - %d%%"%i)
        win.refresh()
    time.sleep(.05)
curses.endwin()
Anurag Uniyal
  • 85,954
  • 40
  • 175
  • 219
2

I had to combine a few answers above to make it work on Python 3.7 / Windows 10. The example runs on Spyder's console:

import sys, time

for i in range(0, 101, 5):
  print("\r>> You have finished {}%".format(i), end='')
  sys.stdout.flush()
  time.sleep(.2)

The time.sleep(.2) is just used to simulates some time-consuming code.

avermaet
  • 1,543
  • 12
  • 33
Rational-IM
  • 2,353
  • 1
  • 9
  • 25
1

using sys.stdout.write() instead of print works in both python 2 and 3 without any compromises.

fjleon
  • 341
  • 1
  • 3
  • 10
1

The OP didn't specify Py2 or Py3. In Python 3 the 'import' of 'sys' and the 'sys.stdout' call can be replaced with 'flush=True':

import time
for i in range(0,101,25):
  print("\r>>TESTING - {:0>3d}%".format(i), end='', flush=True)
  time.sleep(.5)
print()

Thanks to Petr Viktorin for showing the "flush" parameter for Python 3 print(). I submit this because his Python 3 example doesn't include a 'format' specifier. It took me awhile to figure out that the additional parameters go after the 'format' specifier parentheses as shown in my example. I just picked an example format of 3 character integer 0 filled on the left. The best doc I found for Py3 format is: 6.1.3.1. Format Specification Mini-Language

Webtest
  • 21
  • 5