Search code examples
python-3.xterminaliojupyter-notebook

Python '\r' print on the same line but won't erase the previous text


I am trying to print the report for each iteration. Since each iteration takes a really long time to run, therefore, I use print together with end="\r" to show the current item being processed. Here's the dummy code:

import time
y = list(range(50))

print("epoch\ttrain loss\ttest loss\ttrain avg\ttest avg\ttime\tutime")
for e in range(10):
    for i in range(50):
        print("training {}/{} batches".format(i,50), end = '\r')
        time.sleep(0.05)
    print('{}\t{:2f}\t{:2f}\t{:2f}\t{:2f}\t{:2.1f}\t{:2.1f}'.format(y[0]+e,y[1]+e,y[2]+e,y[3]+e,y[4]+e,y[5]+e,y[6]+e)) 

Expected Result

enter image description here This is my expected result, where the progress information is completely erased after each iteration. (I am running it in Jupyter notebook, and it looks fine)

The Result that I am getting

enter image description here However, when I run it on linux terminal, the progress information is not completely erased, and the result is overlaying on top of the progress.

Why is it so? How to solve it?


Solution

  • \r simply moves the cursor back to the beginning of the current line. Anything printed after the \r is printed "on top of" the content previously there. On a real printer/teletype this would be literally true, with two characters getting printed in the same position ("overstruck"). On a terminal, the new characters replace the old ones (but only in positions that you actually write to).

    You can take advantage of this behavior of terminals by printing spaces. You need at least as many spaces as the content you want to erase, but not enough to make the terminal wrap to the next line (this may be impossible if the line was printed all the way to the last character).
    In your case, you know that the line won't be more than 22 characters long, so you could use end='\r \r' (go back to the beginning of the line, print 22 blanks, then go back to the beginning of the line again).