Home > Software engineering >  Correct method of using a carriage return and newlines in python
Correct method of using a carriage return and newlines in python

Time:10-26

Problem

In the two years that I've been coding in python, I've somewhere and somewhere struggled with this problem and therefore I want to ask for the correct way. How do you make it so that it overwrites the previous print, while having newlines (either by returns or \n). I've tried most answers that I could find, however it only does one of the jobs I want it to.


Testing model

import time, sys

counter1 = 0
counter2 = 0
counter3 = 0

for i in range(5):
    time.sleep(0.1)
    counter1  = 1
    counter2  = 1
    counter3  = 1
    
    #print method here!

Attempt 1:

Multiple lined (f)string using """ and \r

    print(f"""\r
Counter 1: {counter1}
Counter 2: {counter2}
Counter 3: {counter3}
    """)

Output of attempt 1:

Counter 1: 1
Counter 2: 1
Counter 3: 1


Counter 1: 2
Counter 2: 2
Counter 3: 2

..etc

Attempt 2:

A normal (f)string using \r and \n

print(f"\rCounter 1: {counter1}\nCounter 2: {counter2}\nCounter 3: {counter3}")

Output of attempt 2:

Counter 1: 1
Counter 2: 1
Counter 3: 1
Counter 1: 2
Counter 2: 2
Counter 3: 2
etc..

Attempt 3:

Using sys.stdout.write, \r and \n

sys.stdout.write(f'\rCounter 1: {counter1}\nCounter 2: {counter2}\nCounter 3: {counter3}')
sys.stdout.flush()  

Output of attempt 3:

Counter 1: 1
Counter 2: 1
Counter 1: 2
Counter 2: 2
Counter 1: 3
etc..

Attempt 4:

Using the carriage return (\r) at the end:

print(f"Counter 1: {counter1}\nCounter 2: {counter2}\nCounter 3: {counter3}\n", end = "\r")

Output of attempt 4:

Counter 1: 1
Counter 2: 1
Counter 3: 1
Counter 1: 2
Counter 2: 2
Counter 3: 2

Attempt 5:

Prints apart from each other with the first one having \r in front of it

print(f"\rCounter 1: {counter1}")
print(f"Counter 2: {counter2}")
print(f"Counter 3: {counter3}")

Output of attempt 5:

Counter 1: 1
Counter 2: 1
Counter 3: 1
Counter 1: 2
Counter 2: 2
Counter 3: 2

CodePudding user response:

Carriage return doesn't undo an entire print or anything, it just returns the cursor to the first column of the current line. Think of the carriage on a typewriter returning to the left side. If you have a newline before the carriage return, then the cursor will just be at the left side of the line below the one you just printed.

To do what you're trying to do, and overwrite previous lines, you'd have to do something like re-print the entire screen's worth of lines, or use something like curses that does it for you.

CodePudding user response:

Adding to alefir's answer, the closest I could come up with was something like this, which puts everything you want to change onto one line. Not sure if it meets the need for your code.

import time

counter1 = 0
counter2 = 0
counter3 = 0

print("%s\t%s\t%s" % ("Counter 1 name", "Counter 2 name", "Counter 3 name"))
for i in range(5):
    time.sleep(0.1)
    counter1  = 1
    counter2  = 1
    counter3  = 1
    print("%.1f\t\t%.1f\t\t%.1f" % (counter1, counter2, counter3), end = "\r")

Alternatively, to implement alefir's approach with multiple lines, you could use something like this to clear the screen:

# import only system from os
from os import system, name

# define our clear function
def clear():
  
    # for windows
    if name == 'nt':
        _ = system('cls')
  
    # for mac and linux(here, os.name is 'posix')
    else:
        _ = system('clear')

Combining with your attempt 1, you would have something like this:

for i in range(5):
    time.sleep(0.1)
    counter1  = 1
    counter2  = 1
    counter3  = 1
    clear()
    print(f"""\r
    Counter 1: {counter1}
    Counter 2: {counter2}
    Counter 3: {counter3}
    """)    
  • Related