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:
- When I start my program,
Hello World
prints.
- And program sleeps 3 seconds.
- 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!
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 ")
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.
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
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.
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:
- When I start my program,
Hello World
prints. - And program sleeps 3 seconds.
- 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!
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 ")
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.
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
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.