Search code examples
pythonpython-3.xnewlinecarriage-return

Correct method of using a carriage return and newlines in python


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

Solution

  • 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}
        """)