How to delete character or line from terminal in Python?

Question:

I want to erase character or line from terminal in Python.

For example, I printed "Hello World" using print("Hello World"). And then I used time.sleep(3) to wait 3 seconds. Then I want to delete one character in terminal, so terminal will be Hello Worl.

So, what I want for result is:

  1. When I start my program, Hello World prints.
  2. And program sleeps 3 seconds.
  3. Then text in terminal changes to Hello Worl.

And also, I found some solutions from SO, and write = sys.stdout.write, write("b") but this prints <0x08>.

Is there any way to delete character or line in terminal?

I’m using Python 3.8 and Windows 10. Thanks!

Asked By: Superjay

||

Answers:

You can do this by using end='r' for your print statement. r makes the cursor stay on the same row, so you can overwrite it.

from time import sleep

print("Hello world", end='r')
sleep(3)
print("Hello worl ")
Answered By: M Z

You should note that the print function ends with a newline by default. To keep the cursor at the end of the line you printed, you should use the end parameter inside the print function:

print("Hello World", end="", flush=True)    # Edited

The reason for using end = '' is to make the print function end with no new character rather than using the default newline.

For the next step, you can use write = sys.stdout.write as you mentioned from the other question, and to avoid any problems in printing spare characters, you can make sure to use write("b b").

The complete code can be written as follows:

import sys, time 

print("Hello World", end="")

time.sleep(3)
write = sys.stdout.write
write('b b')

You could also use sys.stdout.write instead of print function. As far as I know, one of the main differences between these two is that print forces you to start from a new line by default. However, with the above solution and using end = '' there are no concerns anymore.

Answered By: Mahdi

I know this is an old question and you’ve probably found the solution, but it never hurts to help future viewers that have the same question. I see that you’ve commented on the answer marked correct asking if you could erase multiple lines at once. The way I would approach this is like so:

import sys
import time


def go_to_start(text):
    lines = text.split('n') # separate lines
    nlines = len(lines) # number of lines
    sys.stdout.write('x1b[%sA' % (nlines - 1)) # move up to first line
    sys.stdout.write('r') # move to beginning of line


text = '''
this is my
multiline text
'''

text2 = '''
this is not my
multiline paragraph
'''

sys.stdout.write(text) # print text
sys.stdout.flush()
time.sleep(3) # sleep 3 seconds
go_to_start(text) # go to start
sys.stdout.write(text2) # overwrite text

Now, a problem that is very rarely talked about, as far as I’ve noticed, arises. If text2 were to be

text2 = '''
this is
multiline
'''

the original text would be left unchanged. This is because when you move to the start and overwrite text, only the text that is needed to be overwritten is overwritten. In this case, only 'this is' and 'multiline' would be overwritten, leaving ' my' and ' text' untouched. To fix this, you could write a new clear_to_start function, that clears text as the cursor ascends to the top:

def clear_to_start(text):
    lines = text.split('n') # separate lines
    lines = lines[::-1] # reverse list
    nlines = len(lines) # number of lines

    for i, line in enumerate(lines): # iterate through lines from last to first
        sys.stdout.write('r') # move to beginning of line
        sys.stdout.write(' ' * len(line)) # replace text with spaces (thus overwriting it)

        if i < nlines - 1: # not first line of text
            sys.stdout.write('x1b[1A') # move up one line

    sys.stdout.write('r') # move to beginning of line again

This function could then be used like so:

import sys
import time


def clear_to_start(text):
    lines = text.split('n') # separate lines
    lines = lines[::-1] # reverse list
    nlines = len(lines) # number of lines

    for i, line in enumerate(lines): # iterate through lines from last to first
        sys.stdout.write('r') # move to beginning of line
        sys.stdout.write(' ' * len(line)) # replace text with spaces (thus overwriting it)

        if i < nlines - 1: # not first line of text
            sys.stdout.write('x1b[1A') # move up one line

    sys.stdout.write('r') # move to beginning of line again


text = '''
this is my
multiline text
'''

text2 = '''
this is
multiline
'''

sys.stdout.write(text) # print text
sys.stdout.flush()
time.sleep(3) # sleep 3 seconds
clear_to_start(text) # clear lines and ascend to top
sys.stdout.write(text2) # overwrite text
Answered By: Pyzard

Using r lets you return to the beginning of the line, while using the keyword end lets you avoid entering a new line.

from time import sleep


class ProgressBar:

    def __init__(self, length=30):
        self.length = length

    def __call__(self, value, total):
        n = int(self.length * value / (total-1))        
        full = '=' * n
        empty = ' ' * (self.length - n)
        print(end=f'r[{full}{empty}]')


def test():
    bar = ProgressBar(length=20)
    n = 20
    for i in range(n):
        bar(value=i, total=n)
        sleep(0.1)


if __name__ == '__main__':
    test()

For this code to work properly you must not print while progress bar is growing.

Answered By: Omar Cusma Fait
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.