Why not using curses? It works natively in Linux, OSX and now there is also a Windows implementation (as reported here).
The following example would be reliable on most platforms:
from curses import wrapper
import time
def print_over(scr, s):
scr.clear()
scr.addstr(5, 0, s)
scr.refresh()
def main(scr):
for i in range(10, 110, 10):
print_over(scr,'Progress: %d %%'%i)
time.sleep(1)
wrapper(main)
EDIT:
Here another example that does not clear the whole screen:
from curses import tparm, tigetstr, setupterm
import time
def tput(cmd, *args):
print (tparm(tigetstr(cmd), *args), end='') # Emulates Unix tput
class window():
def __init__(s, x, y, w, h):
s.x, s.y, s.w, s.h = x, y, w, h # store window coordinates and size
def __enter__(s):
tput('sc') # saves current cursor position
s.clear() # clears the window
return s
def __exit__(s, exc_type, exc_val, exc_tb):
tput('rc') # restores cursor position
def clear(s, fill=' '):
for i in range(s.h):
tput('cup', s.y+i, s.x) # moves cursor to the leftmost column
print (fill*s.w, end='')
def print_over(s, msg, x, y):
tput('cup', s.y+y, s.x+x)
print (msg, end='')
setupterm()
with window(x=5, y=10, w=80, h=5) as w:
for i in range(10, 110, 10):
w.clear()
w.print_over('Progress: %d %%'%i, 5, 2)
time.sleep(1)
And here another one that overwrites just the last line:
from curses import tparm, tigetstr, setupterm
import time
def tput(cmd, *args):
print (tparm(tigetstr(cmd), *args), end='') # Emulates Unix tput
setupterm()
for i in range(10, 110, 10):
tput('el') # clear to end of line
print (' Progress: %d %%'%i, end='\r')
time.sleep(1)
Basically, the principle is always to use curses
with tput commands to avoid any explicit escape characters.
Note that you might need to flush stdout or just launch the script with python -u
.