31

On Unix, I can either use \r (carriage return) or \b (backspace) to overwrite the current line (print over text already visible) in the shell.

Can I achieve the same effect in a Windows command line from a Python script?

I tried the curses module but it doesn't seem to be available on Windows.

smci
  • 32,567
  • 20
  • 113
  • 146
Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • My [question](http://stackoverflow.com/questions/51212/how-to-write-a-download-progress-indicator-in-python) about a Python Download Progress Indicator might be helpful. – cschol Jan 21 '09 at 13:55
  • Does this answer your question? [Print in one line dynamically](https://stackoverflow.com/questions/3249524/print-in-one-line-dynamically) – Elikill58 May 02 '23 at 06:18

11 Answers11

35

yes:

import sys
import time

def restart_line():
    sys.stdout.write('\r')
    sys.stdout.flush()

sys.stdout.write('some data')
sys.stdout.flush()
time.sleep(2) # wait 2 seconds...
restart_line()
sys.stdout.write('other different data')
sys.stdout.flush()
alberto
  • 2,625
  • 4
  • 29
  • 48
nosklo
  • 217,122
  • 57
  • 293
  • 297
22

I know this is old, but i wanted to tell my version (it works on my PC in the cmd, but not in the idle) to override a line in Python 3:

>>> from time import sleep
>>> for i in range(400):
>>>     print("\r" + str(i), end="")
>>>     sleep(0.5)

EDIT: It works on Windows and on Ubuntu

adho12
  • 395
  • 4
  • 11
14
import sys 
import time

for i in range(10):
    print '\r',         # print is Ok, and comma is needed.
    time.sleep(0.3)
    print i,
    sys.stdout.flush()  # flush is needed.

And if on the IPython-notebook, just like this:

import time
from IPython.display import clear_output

for i in range(10):
    time.sleep(0.25)
    print(i)
    clear_output(wait=True)

http://nbviewer.ipython.org/github/ipython/ipython/blob/master/examples/notebooks/Animations%20Using%20clear_output.ipynb

Raffael
  • 19,547
  • 15
  • 82
  • 160
Honghe.Wu
  • 5,899
  • 6
  • 36
  • 47
7

I just had this problem. You can still use \r, even in Windows Command Prompt, however, it only takes you back to the previous linebreak (\n).

If you do something like this:

cnt = 0
print str(cnt)
while True:
    cnt += 1
    print "\r" + str(cnt)

You'll get:

0
1
2
3
4
5
...

That's because \r only goes back to the last line. Since you already wrote a newline character with the last print statement, your cursor goes from the beginning of a new empty line to the beginning of the same new empty line.

To illustrate, after you print the first 0, your cursor would be here:

0
| # <-- Cursor

When you \r, you go to the beginning of the line. But you're already on the beginning of the line.

The fix is to avoid printing a \n character, so your cursor is on the same line and \r overwrites the text properly. You can do that with print 'text',. The comma prevents the printing of a newline character.

cnt = 0
print str(cnt),
while True:
    cnt += 1
    print "\r" + str(cnt),

Now it will properly rewrite lines.

Note that this is Python 2.7, hence the print statements.

Anubian Noob
  • 13,426
  • 6
  • 53
  • 75
  • The newline-avoidance exactly fixed my problem, thanks! Just as an addition, in Python 3 one can use `print(msg, end=' ')` to avoid newlines. – Thomas Lang May 14 '20 at 07:15
6

Easy method:

import sys
from time import sleep
import os

#print("\033[y coordinate;[x coordinateH Hello")
os.system('cls')
sleep(0.2)
print("\033[1;1H[]")
sleep(0.2)
print("\033[1;1H  []")
sleep(0.2)
print("\033[1;1H    []")
sleep(0.2)
print("\033[1;1H      []")
sleep(0.2)
print("\033[1;1H        []")
sleep(0.2)
print("\033[1;1H      []")
sleep(0.2)
print("\033[1;1H    []")
sleep(0.2)
print("\033[1;1H  []")
sleep(0.2)
print("\033[1;1H[]")
sleep(0.2)
Fahri Güreşçi
  • 569
  • 7
  • 14
3

Simple way if you're just wanting to update the previous line:

import time
for i in range(20):
    print str(i) + '\r',
    time.sleep(1)
Dustin Wyatt
  • 4,046
  • 5
  • 31
  • 60
2

Easiest way is to use two \r - one at the beginning and one at the end

for i in range(10000):
    print('\r'+str(round(i*100/10000))+'%  Complete\r'),

It will go pretty quickly

bfree67
  • 669
  • 7
  • 6
  • 1
    :-/ The first `\r` will be processed 9999 times for naught. If you don't know where your cursor is, you can call `print('\r')` *once* before the loop. – Aaron Digulla Sep 04 '17 at 09:56
1

Thanks for all the useful answers in here guys. I needed this :)

I found nosklo's answer particularly useful, but I wanted something fully contained within a function by passing the desired output as a parameter. Also, I didn't really need the timer, since I wanted the printing to take place after a specific event).

This is what did the trick for me, I hope someone else finds it useful:

import sys

def replace_cmd_line(output):
    """Replace the last command line output with the given output."""
    sys.stdout.write(output)
    sys.stdout.flush()
    sys.stdout.write('\r')
    sys.stdout.flush()
  • You need just a single flush() at the end. I'm not sure `sys.stdout.write(output + '\r')` would be that much faster than two method calls (because of allocating memory for the string, copying, GC), so keeping them separate is probably OK. – Aaron Digulla Jan 25 '17 at 09:47
1

Yes, this question was asked 11 years ago but it's cool. I like to improvise. Add-on to nosklo's answer:

import sys
import time

def restart_line():
    sys.stdout.write("\r")
    sys.stdout.flush()

string_one = "some data that is very long..."
sys.stdout.write(string_one)
sys.stdout.flush()

time.sleep(2)
restart_line()

string_two = "shorter data"
if len(string_two) < len(string_one):
    string_two = string_two+(" "*int((len(string_one)-len(string_two))))
    # This will overwrite the characters that would be left on the console

sys.stdout.write(string_two)
sys.stdout.flush()
SUPER MECH M500
  • 104
  • 2
  • 3
  • 19
1

Tested on PyCharm 2020.3 and Python version 3.9, to overwrite written printout I use the following:

from time import sleep

for x in range(10):
    print(f'\r {x}', end='')
    sleep(0.6)

That's the code I mainly use for my programs. Using end='\r' will overwrite the whole text for me, ignoring sleep.

In real scenario, I set it up as follows:

    def progress_callback(progress):
        print(f'\rDownloading File: {progress.dlable.file_name}  Progress: ' + '{0:.2f}%'.format(progress.percent), end='')
        # `return True` if the download should be canceled
        return False

    print('\nDownload complete!)

The print after the overwrite function has to be in new line, or the same line before will be overwritten.

Neek0tine
  • 11
  • 4
1

On Windows (python 3), it seems to work (not using stdout directly):

import sys

for i in reversed(range(0,20)):
  time.sleep(0.1)
  if(i == 19):
    print(str(i), end='', file=sys.stdout)
  else:
    print("\r{0:{width}".format(str(i), width = w, fill = ' ', align = 'right'), end='', file=sys.stdout)
  sys.stdout.flush()
  w = len(str(i))

The same line is updated everytime print function is called.

This algorithm can be improved, but it is posted to show what you can do. You can modify the method according to your needs.

Jesufer Vn
  • 13,200
  • 6
  • 20
  • 26