Related
I'm writing an arcanoid game in python on windows console and what bothers me is annoying blinking after every iteration of "displaying" loop. Does anyone have any idea how to reduce it? This is part of the code:
#-*- coding: UTF-8 -*-
import time
import os
clear = lambda: os.system('cls')
def gra():
koniec='0'
while koniec!='1':
for i in range(4):
for j in range(10):
print '[___]',
print '\n',
for i in range(10):
print '\n'
for i in range(10):
print ' ',
print '~~~~~~~~~~'
time.sleep(0.1)
clear()
gra()
There is a limit to what you can do, but gathering everything into 1 big string and then printing once between screen clears is better than a number of small prints in a loop. Run the following code and look how much better the second half of the program runs than the first half:
import time, os, random
def display1(chars):
os.system('cls')
for row in chars:
print(''.join(row))
def display2(chars):
os.system('cls')
print('\n'.join(''.join(row) for row in chars))
chars = []
for i in range(40):
chars.append(["-"]*40)
for i in range(100):
r = random.randint(0,39)
c = random.randint(0,39)
chars[r][c] = "X"
time.sleep(0.1)
display1(chars)
os.system('cls')
time.sleep(1)
chars = []
for i in range(40):
chars.append(["-"]*40)
for i in range(100):
r = random.randint(0,39)
c = random.randint(0,39)
chars[r][c] = "X"
time.sleep(0.1)
display2(chars)
On Edit: You can combine these ideas with the excellent idea of #GingerPlusPlus to avoid cls. The trick is to print a large number of backspaces.
First -- write your own version of cls:
def cls(n = 0):
if n == 0:
os.system('cls')
else:
print('\b'*n)
The first time it is called -- pass it zero and it just clear the screen.
The following function pushes a character array to the command window in one big print and returns the number of characters printed (since this is the number of backspaces needed to reposition the cursor):
def display(chars):
s = '\n'.join(''.join(row) for row in chars)
print(s)
return len(s)
Used like thus:
chars = []
for i in range(40):
chars.append(["-"]*40)
for i in range(100):
n = 0
r = random.randint(0,39)
c = random.randint(0,39)
chars[r][c] = "X"
time.sleep(0.1)
cls(n)
n = display(chars)
when the above code is run, the display changes smoothly with virtually no flicker.
You could do:
rows_full=row_count+2
print("\033[F"*rows_full)
#print the screen again
The disadvantages are that you can't overwrite the very top bit of the console, and have to know how many rows have been printed. But knowing the row amount should be trivial when working with a fixed-rowed ASCII graphics game. It also isn't a CLS, it just moves you to the top.
Oh, the explanation! It uses the ANSI escape sequence F, which moves to the row above. It prints this many times, which puts you to the top of the screen. Also, you have to add 2 to the rowcount, otherwise the top rows will repeat.
PS: If anyone knows how to make it so that that method can reach the top part of the console, I'll give you some cookies.
I figured it out... You can use ANSI codes to move the cursor then clear the lines without any BLINK!
print('\033[4A\033[2K', end='')
\033[4A Moves the cursor 4 lines up (\033[{lines}A you can replace lines with however many you need)
\033[2K Clears all those lines without the screen blinking.
You can use it in a simple typewrite function that needs a constant message or a box around it like this:
from time import sleep
def typewrite(text: str):
lines = text.split('\n')
for line in lines:
display = ''
for char in line:
display += char
print(f'╭─ SOME MESSAGE OR SOMEONES NAME ────────────────────────────────────────────╮')
print(f'│ {display:74} │') # :74 is the same as ' ' * 74
print(f'╰────────────────────────────────────────────────────────────────────────────╯')
sleep(0.05)
print('\033[3A\033[2K', end='')
The only problem with this is that the top line is blinking. To fix this all we need to do is to add a empty line that is blinking so the user cant see it. We also move the cursor up from 3 to 4 lines.
def typewrite(text: str):
lines = text.split('\n')
for line in lines:
display = ''
for char in line:
display += char
print('')
print(f'╭─ SOME MESSAGE OR SOMEONES NAME ────────────────────────────────────────────╮')
print(f'│ {display:74} │') # :74 is the same as ' ' * 74
print(f'╰────────────────────────────────────────────────────────────────────────────╯')
sleep(0.05)
print('\033[4A\033[2K', end='')
To make this into your code just print your text and add a print('') at the start. Then use this print('\033[4A\033[2K', end='') but change the 4 to however many lines that you printed including the print(''). Then it should work without blinking. You can put print('\033[4B', end='') at the end which just moves the cursor back up.
If you want to hide the cursor you can use this gibberish or make the cursor the same color as the background:
import ctypes
if os.name == 'nt':
class _CursorInfo(ctypes.Structure):
_fields_ = [("size", ctypes.c_int),
("visible", ctypes.c_byte)]
def hide_cursor() -> None:
if os.name == 'nt':
ci = _CursorInfo()
handle = ctypes.windll.kernel32.GetStdHandle(-11)
ctypes.windll.kernel32.GetConsoleCursorInfo(handle, ctypes.byref(ci))
ci.visible = False
ctypes.windll.kernel32.SetConsoleCursorInfo(handle, ctypes.byref(ci))
def show_cursor() -> None:
if os.name == 'nt':
ci = _CursorInfo()
handle = ctypes.windll.kernel32.GetStdHandle(-11)
ctypes.windll.kernel32.GetConsoleCursorInfo(handle, ctypes.byref(ci))
ci.visible = True
ctypes.windll.kernel32.SetConsoleCursorInfo(handle, ctypes.byref(ci))
Note: All of this is still new to me so I am still testing this out to fully understand it.
anything really done with the windows console will blink if your clearing and rewriting the screen, unless you find something quite advanced I don't think you can remove the blinking
my only suggestion is to limit the clearing to when something actually changes.
or to use a tkinter text box instead of the cmd. If you want to use that idea I can help with it, although I mostly use tkinter for python 3.4
hopefully that helps!
Just like in the movies and in games, the location of a place comes up on screen as if it's being typed live. I want to make a game about escaping a maze in python. At the start of the game it gives the background information of the game:
line_1 = "You have woken up in a mysterious maze"
line_2 = "The building has 5 levels"
line_3 = "Scans show that the floors increase in size as you go down"
Under the variables, I tried to do a for loop for each line similar to this:
from time import sleep
for x in line_1:
print (x)
sleep(0.1)
The only problem with this is that it print one letter per line. The timing of it is ok, but how can I get it to go on one line?
Because you tagged your question with python 3 I will provide a python 3 solution:
Change your end character of print to an empty string: print(..., end='')
Add sys.stdout.flush() to make it print instantly (because the output is buffered)
Final code:
from time import sleep
import sys
for x in line_1:
print(x, end='')
sys.stdout.flush()
sleep(0.1)
Making it random is also very simple.
Add this import:
from random import uniform
Change your sleep call to the following:
sleep(uniform(0, 0.3)) # random sleep from 0 to 0.3 seconds
lines = ["You have woken up in a mysterious maze",
"The building has 5 levels",
"Scans show that the floors increase in size as you go down"]
from time import sleep
import sys
for line in lines: # for each line of text (or each message)
for c in line: # for each character in each line
print(c, end='') # print a single character, and keep the cursor there.
sys.stdout.flush() # flush the buffer
sleep(0.1) # wait a little to make the effect look good.
print('') # line break (optional, could also be part of the message)
To iterate over the lines, change the loop to:
for x in (line_1, line_2, line_3):
You can change the end of line character automatically added by print with print("", end=""). To printfoobar, you could do this:
print("foo", end="")
print("bar", end="")
From the documentation:
All non-keyword arguments are converted to strings like str() does and written to the stream, separated by sep and followed by end. Both sep and end must be strings; they can also be None, which means to use the default values.
Python Typewriter Effect
For every letter in the string, my answer provides 0.1 of a second to wait, so the text would appear one by one. Python 3 allows the use of sys.stdout.write.
import time, sys
def anything(str):
for letter in str:
sys.stdout.write(letter)
sys.stdout.flush()
time.sleep(0.1)
anything("Blah Blah Blah...")
Your full code will look like this:
import time, sys
def anything(str):
for letter in str:
sys.stdout.write(letter)
sys.stdout.flush()
time.sleep(0.1)
anything("You have woken up in a
mysterious maze")
anything("The building has five
levels")
anything("Scans show that the floors
increase in size as you go down")
It's easiest solving:
import time
def tt(text, delay):
for i in text:
print(end = i)
time.sleep(delay)
print(tt("sample text", 0.2)
This solution will not change ur algorithm
from time import sleep
line_1 = "You have woken up in a mysterious maze"
line_2 = "The building has 5 levels"
line_3 = "Scans show that the floors increase in size as you go down"
for x in line_1:
print(x, end='')
sleep(0.05)
I want to run a script, which basically shows an output like this:
Installing XXX... [DONE]
Currently, I print Installing XXX... first and then I print [DONE].
How can I instead print Installing xxx... and [DONE] on the same line?
For the specific problem of writing a new message on the same line, replacing what was there before, please see How to overwrite the previous print to stdout?. Most answers here interpreted the question as being about writing new text at the end of the current line.
For the problem of using a single print to output multiple things at once, see How can I print multiple things (fixed text and/or variable values) on the same line, all at once?.
Python 3 Solution
The print() function accepts an end parameter which defaults to \n (new line). Setting it to an empty string prevents it from issuing a new line at the end of the line.
def install_xxx():
print("Installing XXX... ", end="", flush=True)
install_xxx()
print("[DONE]")
Python 2 Solution
Putting a comma on the end of the print() line prevents print() from issuing a new line (you should note that there will be an extra space at the end of the output).
def install_xxx():
print "Installing XXX... ",
install_xxx()
print "[DONE]"
You can simply use this:
print 'something',
...
print ' else',
and the output will be
something else
no need to overkill by import sys. Pay attention to comma symbol at the end.
Python 3+
print("some string", end=""); to remove the newline insert at the end. Read more by help(print);
You should use backspace '\r' or ('\x08') char to go back on previous position in console output
Python 2+:
import time
import sys
def backspace(n):
sys.stdout.write((b'\x08' * n).decode()) # use \x08 char to go back
for i in range(101): # for 0 to 100
s = str(i) + '%' # string for output
sys.stdout.write(s) # just print
sys.stdout.flush() # needed for flush when using \x08
backspace(len(s)) # back n chars
time.sleep(0.2) # sleep for 200ms
Python 3:
import time
def backline():
print('\r', end='') # use '\r' to go back
for i in range(101): # for 0 to 100
s = str(i) + '%' # string for output
print(s, end='') # just print and flush
backline() # back to the beginning of line
time.sleep(0.2) # sleep for 200ms
This code will count from 0% to 100% on one line. Final value will be:
> python test.py
100%
Additional info about flush in this case here: Why do python print statements that contain 'end=' arguments behave differently in while-loops?
Use sys.stdout.write('Installing XXX... ') and sys.stdout.write('Done'). In this way, you have to add the new line by hand with "\n" if you want to recreate the print functionality. I think that it might be unnecessary to use curses just for this.
Most simple:
Python 3
print('\r' + 'something to be override', end='')
It means it will back the cursor to beginning, than will print something and will end in the same line. If in a loop it will start printing in the same place it starts.
None of the answers worked for me since they all paused until a new line was encountered. I wrote a simple helper:
def print_no_newline(string):
import sys
sys.stdout.write(string)
sys.stdout.flush()
To test it:
import time
print_no_newline('hello ')
# Simulate a long task
time.sleep(2)
print('world')
"hello " will first print out and flush to the screen before the sleep. After that you can use standard print.
sys.stdout.write will print without return carriage
import sys
sys.stdout.write("installing xxx")
sys.stdout.write(".")
http://en.wikibooks.org/wiki/Python_Programming/Input_and_output#printing_without_commas_or_newlines
Python appends newline as an end to print. Use end=' ' for python3 for print method to append a space instead of a newline. for python2 use comma at end of print statement.
print('Foo', end=' ')
print('Bar')
This simple example will print 1-10 on the same line.
for i in range(1,11):
print (i, end=" ")
Print has an optional end argument, it is what printed in the end.
The default is a newline, but you can change it to empty string. e.g. print("hello world!", end="")
If you want to overwrite the previous line (rather than continually adding to it), you can combine \r with print(), at the end of the print statement. For example,
from time import sleep
for i in xrange(0, 10):
print("\r{0}".format(i)),
sleep(.5)
print("...DONE!")
will count 0 to 9, replacing the old number in the console. The "...DONE!" will print on the same line as the last counter, 9.
In your case for the OP, this would allow the console to display percent complete of the install as a "progress bar", where you can define a begin and end character position, and update the markers in between.
print("Installing |XXXXXX | 30%"),
Here a 2.7-compatible version derived from the 3.0 version by #Vadim-Zin4uk:
Python 2
import time
for i in range(101): # for 0 to 100
s = str(i) + '%' # string for output
print '{0}\r'.format(s), # just print and flush
time.sleep(0.2)
For that matter, the 3.0 solution provided looks a little bloated. For example, the backspace method doesn't make use of the integer argument and could probably be done away with altogether.
Python 3
import time
for i in range(101): # for 0 to 100
s = str(i) + '%' # string for output
print('{0}\r'.format(s), end='') # just print and flush
time.sleep(0.2) # sleep for 200ms
Both have been tested and work.
This is a very old thread, but here's a very thorough answer and sample code.
\r is the string representation of Carriage Return from the ASCII character set. It's the same as octal 015 [chr(0o15)] or hexidecimal 0d [chr(0x0d)] or decimal 13 [chr(13)]. See man ascii for a boring read. It (\r) is a pretty portable representation and is easy enough for people to read. It very simply means to move the carriage on the typewriter all the way back to the start without advancing the paper. It's the CR part of CRLF which means Carriage Return and Line Feed.
print() is a function in Python 3. In Python 2 (any version that you'd be interested in using), print can be forced into a function by importing its definition from the __future__ module. The benefit of the print function is that you can specify what to print at the end, overriding the default behavior of \n to print a newline at the end of every print() call.
sys.stdout.flush tells Python to flush the output of standard output, which is where you send output with print() unless you specify otherwise. You can also get the same behavior by running with python -u or setting environment variable PYTHONUNBUFFERED=1, thereby skipping the import sys and sys.stdout.flush() calls. The amount you gain by doing that is almost exactly zero and isn't very easy to debug if you conveniently forget that you have to do that step before your application behaves properly.
And a sample. Note that this runs perfectly in Python 2 or 3.
from __future__ import print_function
import sys
import time
ANS = 42
FACTORS = {n for n in range(1, ANS + 1) if ANS % n == 0}
for i in range(1, ANS + 1):
if i in FACTORS:
print('\r{0:d}'.format(i), end='')
sys.stdout.flush()
time.sleep(ANS / 100.0)
else:
print()
This solution in Python 3.X specific:
When I need to do this, I'll generally just use
end=' '
For example:
# end='' ends the output with a <space>
print("Welcome to" , end = ' ')
print("stackoverflow", end = ' ')
This outputs as:
Welcome to stackoverflow
The space in end= can be replaced with any character. For example,
print("Welcome to" , end = '...')
print("stackoverflow", end = '!')
Which outputs as:
Welcome to...stackoverflow!
print() has a built in parameter "end" that is by default set to "\n"
Calling print("This is America") is actually calling print("This is America", end = "\n").
An easy way to do is to call print("This is America", end ="")
Just in case you have pre-stored the values in an array, you can call them in the following format:
for i in range(0,n):
print arr[i],
Found this Quora post, with this example which worked for me (python 3),
which was closer to what I needed it for (i.e. erasing the whole previous line).
The example they provide:
def clock():
while True:
print(datetime.now().strftime("%H:%M:%S"), end="\r")
For printing the on the same line, as others have suggested, just use end=""
I found this solution, and it's working on Python 2.7
# Working on Python 2.7 Linux
import time
import sys
def backspace(n):
print('\r', end='') # use '\r' to go back
for i in range(101): # for 0 to 100
s = str(i) + '%' # string for output
sys.stdout.write(string)
backspace(len(s)) # back for n chars
sys.stdout.flush()
time.sleep(0.2) # sleep for 200ms
If I had the following code:
for x in range(10):
print(x)
I would get the output of
1
2
etc..
What I would like to do is instead of printing a newline, I want to replace the previous value and overwrite it with the new value on the same line.
Simple Version
One way is to use the carriage return ('\r') character to return to the start of the line without advancing to the next line.
Python 3
for x in range(10):
print(x, end='\r')
print()
Python 2.7 forward compatible
from __future__ import print_function
for x in range(10):
print(x, end='\r')
print()
Python 2.7
for x in range(10):
print '{}\r'.format(x),
print
Python 2.0-2.6
for x in range(10):
print '{0}\r'.format(x),
print
In the latter two (Python 2-only) cases, the comma at the end of the print statement tells it not to go to the next line. The last print statement advances to the next line so your prompt won't overwrite your final output.
Line Cleaning
If you can’t guarantee that the new line of text is not shorter than the existing line, then you just need to add a “clear to end of line” escape sequence, '\x1b[1K' ('\x1b' = ESC):
for x in range(75):
print('*' * (75 - x), x, end='\x1b[1K\r')
print()
Since I ended up here via Google but am using Python 3, here's how this would work in Python 3:
for x in range(10):
print("Progress {:2.1%}".format(x / 10), end="\r")
Related answer here: How can I suppress the newline after a print statement?
#Mike DeSimone answer will probably work most of the time. But...
for x in ['abc', 1]:
print '{}\r'.format(x),
-> 1bc
This is because the '\r' only goes back to the beginning of the line but doesn't clear the output.
If POSIX support is enough for you, the following would clear the current line and leave the cursor at its beginning:
print '\x1b[2K\r',
It uses ANSI escape code to clear the terminal line. More info can be found in wikipedia and in this great talk.
Other approach
This other, (arguably worse) solution I have found looks like this:
last_x = ''
for x in ['abc', 1]:
print ' ' * len(str(last_x)) + '\r',
print '{}\r'.format(x),
last_x = x
-> 1
One advantage is that it will work on windows too.
I had the same question before visiting this thread. For me the sys.stdout.write worked only if I properly flush the buffer i.e.
for x in range(10):
sys.stdout.write('\r'+str(x))
sys.stdout.flush()
Without flushing, the result is printed only at the end out the script
Suppress the newline and print \r.
print 1,
print '\r2'
or write to stdout:
sys.stdout.write('1')
sys.stdout.write('\r2')
for x in range(10):
time.sleep(0.5) # shows how its working
print("\r {}".format(x), end="")
time.sleep(0.5) is to show how previous output is erased and new output is printed
"\r" when its at the start of print message , it gonna erase previous output before new output.
Try this:
import time
while True:
print("Hi ", end="\r")
time.sleep(1)
print("Bob", end="\r")
time.sleep(1)
It worked for me. The end="\r" part is making it overwrite the previous line.
WARNING!
If you print out hi, then print out hello using \r, you’ll get hillo because the output wrote over the previous two letters. If you print out hi with spaces (which don’t show up here), then it will output hi. To fix this, print out spaces using \r.
This works on Windows and python 3.6
import time
for x in range(10):
time.sleep(0.5)
print(str(x)+'\r',end='')
Here's a cleaner, more "plug-and-play", version of #Nagasaki45's answer. Unlike many other answers here, it works properly with strings of different lengths. It achieves this by clearing the line with just as many spaces as the length of the last line printed print. Will also work on Windows.
def print_statusline(msg: str):
last_msg_length = len(getattr(print_statusline, 'last_msg', ''))
print(' ' * last_msg_length, end='\r')
print(msg, end='\r')
sys.stdout.flush() # Some say they needed this, I didn't.
setattr(print_statusline, 'last_msg', msg)
Usage
Simply use it like this:
for msg in ["Initializing...", "Initialization successful!"]:
print_statusline(msg)
time.sleep(1)
This small test shows that lines get cleared properly, even for different lengths:
for i in range(9, 0, -1):
print_statusline("{}".format(i) * i)
time.sleep(0.5)
I couldn't get any of the solutions on this page to work for IPython, but a slight variation on #Mike-Desimone's solution did the job: instead of terminating the line with the carriage return, start the line with the carriage return:
for x in range(10):
print '\r{0}'.format(x),
Additionally, this approach doesn't require the second print statement.
The accepted answer is not perfect. The line that was printed first will stay there and if your second print does not cover the entire new line, you will end up with garbage text.
To illustrate the problem save this code as a script and run it (or just take a look):
import time
n = 100
for i in range(100):
for j in range(100):
print("Progress {:2.1%}".format(j / 100), end="\r")
time.sleep(0.01)
print("Progress {:2.1%}".format(i / 100))
The output will look something like this:
Progress 0.0%%
Progress 1.0%%
Progress 2.0%%
Progress 3.0%%
What works for me is to clear the line before leaving a permanent print. Feel free to adjust to your specific problem:
import time
ERASE_LINE = '\x1b[2K' # erase line command
n = 100
for i in range(100):
for j in range(100):
print("Progress {:2.1%}".format(j / 100), end="\r")
time.sleep(0.01)
print(ERASE_LINE + "Progress {:2.1%}".format(i / 100)) # clear the line first
And now it prints as expected:
Progress 0.0%
Progress 1.0%
Progress 2.0%
Progress 3.0%
I'm a bit surprised nobody is using the backspace character. Here's one that uses it.
import sys
import time
secs = 1000
while True:
time.sleep(1) #wait for a full second to pass before assigning a second
secs += 1 #acknowledge a second has passed
sys.stdout.write(str(secs))
for i in range(len(str(secs))):
sys.stdout.write('\b')
Here's my solution! Windows 10, Python 3.7.1
I'm not sure why this code works, but it completely erases the original line. I compiled it from the previous answers. The other answers would just return the line to the beginning, but if you had a shorter line afterwards, it would look messed up like hello turns into byelo.
import sys
#include ctypes if you're on Windows
import ctypes
kernel32 = ctypes.windll.kernel32
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
#end ctypes
def clearline(msg):
CURSOR_UP_ONE = '\033[K'
ERASE_LINE = '\x1b[2K'
sys.stdout.write(CURSOR_UP_ONE)
sys.stdout.write(ERASE_LINE+'\r')
print(msg, end='\r')
#example
ig_usernames = ['beyonce','selenagomez']
for name in ig_usernames:
clearline("SCRAPING COMPLETE: "+ name)
Output - Each line will be rewritten without any old text showing:
SCRAPING COMPLETE: selenagomez
Next line (rewritten completely on same line):
SCRAPING COMPLETE: beyonce
(Python3) This is what worked for me. If you just use the \010 then it will leave characters, so I tweaked it a bit to make sure it's overwriting what was there. This also allows you to have something before the first print item and only removed the length of the item.
print("Here are some strings: ", end="")
items = ["abcd", "abcdef", "defqrs", "lmnop", "xyz"]
for item in items:
print(item, end="")
for i in range(len(item)): # only moving back the length of the item
print("\010 \010", end="") # the trick!
time.sleep(0.2) # so you can see what it's doing
One more answer based on the prevous answers.
Content of pbar.py:
import sys, shutil, datetime
last_line_is_progress_bar=False
def print2(print_string):
global last_line_is_progress_bar
if last_line_is_progress_bar:
_delete_last_line()
last_line_is_progress_bar=False
print(print_string)
def _delete_last_line():
sys.stdout.write('\b\b\r')
sys.stdout.write(' '*shutil.get_terminal_size((80, 20)).columns)
sys.stdout.write('\b\r')
sys.stdout.flush()
def update_progress_bar(current, total):
global last_line_is_progress_bar
last_line_is_progress_bar=True
completed_percentage = round(current / (total / 100))
current_time=datetime.datetime.now().strftime('%m/%d/%Y-%H:%M:%S')
overhead_length = len(current_time+str(current))+13
console_width = shutil.get_terminal_size((80, 20)).columns - overhead_length
completed_width = round(console_width * completed_percentage / 100)
not_completed_width = console_width - completed_width
sys.stdout.write('\b\b\r')
sys.stdout.write('{}> [{}{}] {} - {}% '.format(current_time, '#'*completed_width, '-'*not_completed_width, current,
completed_percentage),)
sys.stdout.flush()
Usage of script:
import time
from pbar import update_progress_bar, print2
update_progress_bar(45,200)
time.sleep(1)
update_progress_bar(70,200)
time.sleep(1)
update_progress_bar(100,200)
time.sleep(1)
update_progress_bar(130,200)
time.sleep(1)
print2('some text that will re-place current progress bar')
time.sleep(1)
update_progress_bar(111,200)
time.sleep(1)
print('\n') # without \n next line will be attached to the end of the progress bar
print('built in print function that will push progress bar one line up')
time.sleep(1)
update_progress_bar(111,200)
time.sleep(1)
Better to overwrite the whole line otherwise the new line will mix with the old ones if the new line is shorter.
import time, os
for s in ['overwrite!', 'the!', 'whole!', 'line!']:
print(s.ljust(os.get_terminal_size().columns - 1), end="\r")
time.sleep(1)
Had to use columns - 1 on Windows.
This worked for me, using Python 3.7.9 within Spyder, in Windows:
from IPython.display import clear_output
from time import sleep
def print_and_overwrite(text):
'''Remember to add print() after the last print that you want to overwrite.'''
clear_output(wait=True)
print(text, end='\r')
for i in range(15):
#I print the results backwards (from 15 to 1), to test shorter strings
message = "Iteration %d out of 15" %(15-i)
print_and_overwrite(message)
sleep(0.5)
print() #This stops the overwriting
print("This will be on a new line")
Anyway if somebody wants to overprint (clear) a many lines previously printed in stdout, than this answer should be helpful for him. (Thanks Thijmen Dam for the nice article Overwrite Previously Printed Lines)
In ANSI console you can use special sequences:
\033[1A and \033[K
First of them lift up a cursor, second - erase a line entirely.
Example of the clearing a console (Python 3):
LINE_UP = '\033[1A'
LINE_CLEAR = '\033[K'
CONSOLE_HEIGHT = 24 #lines
def clear_console():
for a in range(CONSOLE_HEIGHT):
print(LINE_UP, end=LINE_CLEAR, flush=True)
or eventually simply (will clear screen and move cursor to 0,0):
print('\033[2J', end='', flush=True)
If you want just positioning cursor, then use this:
print('\033[<L>;<C>f', end='', flush=True)
where <L> and <C> are Line and Column correspondingly.
Handful reference for you ANSI escape sequences
This question already has answers here:
How to overwrite the previous print to stdout?
(18 answers)
Why doesn't print output show up immediately in the terminal when there is no newline at the end?
(1 answer)
Closed last month.
Basically I want to do the opposite of what this guy did... hehe.
Python Script: Print new line each time to shell rather than update existing line
I have a program that is telling me how far along it is.
for i in some_list:
#do a bunch of stuff.
print i/len(some_list)*100," percent complete"
So if len(some_list) was 50, I'd get that last line printed 50 times over. I want to print one line and keep updating that line. I know I know this is probably the lamest question you'll read all day. I just can't figure out the four words I need to put into google to get the answer.
Update! I tried mvds' suggestion which SEEMED right. The new code
print percent_complete," \r",
Percent complete is just a string (I was abstracting the first time now I an trying to be literal). The result now is that it runs the program, doesn't print ANYTHING until after the program is over, and then prints "100 percent complete" on one and only one line.
Without the carriage return (but with the comma, half of mvds' suggestion) it prints nothing until the end. And then prints:
0 percent complete 2 percent complete 3 percent complete 4 percent complete
And so on. So now the new issue is that with the comma it doesn't print until the program is finished.
With the carriage return and no comma it behaves the exact same as with neither.
It's called the carriage return, or \r
Use
print i/len(some_list)*100," percent complete \r",
The comma prevents print from adding a newline. (and the spaces will keep the line clear from prior output)
Also, don't forget to terminate with a print "" to get at least a finalizing newline!
From python 3.x you can do:
print('bla bla', end='')
(which can also be used in Python 2.6 or 2.7 by putting from __future__ import print_function at the top of your script/module)
Python console progressbar example:
import time
# status generator
def range_with_status(total):
""" iterate from 0 to total and show progress in console """
n=0
while n<total:
done = '#'*(n+1)
todo = '-'*(total-n-1)
s = '<{0}>'.format(done+todo)
if not todo:
s+='\n'
if n>0:
s = '\r'+s
print(s, end='')
yield n
n+=1
# example for use of status generator
for i in range_with_status(10):
time.sleep(0.1)
For me, what worked was a combo of Remi's and siriusd's answers:
from __future__ import print_function
import sys
print(str, end='\r')
sys.stdout.flush()
In Python 3.3+ you don’t need sys.stdout.flush(). print(string, end='', flush=True) works.
So
print('foo', end='')
print('\rbar', end='', flush=True)
will overwrite ‘foo’ with ‘bar’.
for Console you'll probably need
sys.stdout.flush()
to force update. I think using , in print will block stdout from flushing and somehow it won't update
Late to the game - but since the none of the answers worked for me (I didn't try them all) and I've come upon this answer more than once in my search ... In python 3, this solution is pretty elegant and I believe does exactly what the author is looking for, it updates a single statement on the same line. Note, you may have to do something special if the line shrinks instead of grows (like perhaps make the string a fixed length with padded spaces at the end)
if __name__ == '__main__':
for i in range(100):
print("", end=f"\rPercentComplete: {i} %")
time.sleep(0.2)
As of end of 2020 and Python 3.8.5 on linux console for me only this works:
print('some string', end='\r')
Credit goes to: This post
If you are using Spyder, the lines just print continuously with all the previous solutions. A way to avoid that is using:
for i in range(1000):
print('\r' + str(round(i/len(df)*100,1)) + '% complete', end='')
sys.stdout.flush()
This works for me, hacked it once to see if it is possible, but never actually used in my program (GUI is so much nicer):
import time
f = '%4i %%'
len_to_clear = len(f)+1
clear = '\x08'* len_to_clear
print 'Progress in percent:'+' '*(len_to_clear),
for i in range(123):
print clear+f % (i*100//123),
time.sleep(0.4)
raw_input('\nDone')
As of 2021, for Python 3.9.0 the following solution worked for me in Windows 10, Pycharm.
print('\r some string ', end='', flush=True)
import time
import sys
def update_pct(w_str):
w_str = str(w_str)
sys.stdout.write("\b" * len(w_str))
sys.stdout.write(" " * len(w_str))
sys.stdout.write("\b" * len(w_str))
sys.stdout.write(w_str)
sys.stdout.flush()
for pct in range(0, 101):
update_pct("{n}%".format(n=str(pct)))
time.sleep(0.1)
\b will move the location of the cursor back one space
So we move it back all the way to the beginning of the line
We then write spaces to clear the current line - as we write spaces the cursor moves forward/right by one
So then we have to move the cursor back at the beginning of the line before we write our new data
Tested on Windows cmd using Python 2.7
Try it like this:
for i in some_list:
#do a bunch of stuff.
print i/len(some_list)*100," percent complete",
(With a comma at the end.)
For Python 3+
for i in range(5):
print(str(i) + '\r', sep='', end ='', file = sys.stdout , flush = False)
In those cases, with python 3.x, I'm using the following code:
for ii in range(100):
print(f"\rPercent: {ii+1} %", end=" "*20)
The problem with some other answers is that if your printed string goes shorter at one step, the last characters from the previous string won't be overwrited.
So I use end=" "*20 in order to overwrite the previous line with whitespace. Just make sure that 20 is longer than the length of your longest string.
Based on Remi answer for Python 2.7+ use this:
from __future__ import print_function
import time
# status generator
def range_with_status(total):
""" iterate from 0 to total and show progress in console """
import sys
n = 0
while n < total:
done = '#' * (n + 1)
todo = '-' * (total - n - 1)
s = '<{0}>'.format(done + todo)
if not todo:
s += '\n'
if n > 0:
s = '\r' + s
print(s, end='\r')
sys.stdout.flush()
yield n
n += 1
# example for use of status generator
for i in range_with_status(50):
time.sleep(0.2)
For Python 3.6+ and for any list rather than just ints, as well as using the entire width of your console window and not crossing over to a new line, you could use the following:
note: please be informed, that the function get_console_with() will work only on Linux based systems, and as such you have to rewrite it to work on Windows.
import os
import time
def get_console_width():
"""Returns the width of console.
NOTE: The below implementation works only on Linux-based operating systems.
If you wish to use it on another OS, please make sure to modify it appropriately.
"""
return int(os.popen('stty size', 'r').read().split()[1])
def range_with_progress(list_of_elements):
"""Iterate through list with a progress bar shown in console."""
# Get the total number of elements of the given list.
total = len(list_of_elements)
# Get the width of currently used console. Subtract 2 from the value for the
# edge characters "[" and "]"
max_width = get_console_width() - 2
# Start iterating over the list.
for index, element in enumerate(list_of_elements):
# Compute how many characters should be printed as "done". It is simply
# a percentage of work done multiplied by the width of the console. That
# is: if we're on element 50 out of 100, that means we're 50% done, or
# 0.5, and we should mark half of the entire console as "done".
done = int(index / total * max_width)
# Whatever is left, should be printed as "unfinished"
remaining = max_width - done
# Print to the console.
print(f'[{done * "#"}{remaining * "."}]', end='\r')
# yield the element to work with it
yield element
# Finally, print the full line. If you wish, you can also print whitespace
# so that the progress bar disappears once you are done. In that case do not
# forget to add the "end" parameter to print function.
print(f'[{max_width * "#"}]')
if __name__ == '__main__':
list_of_elements = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
for e in range_with_progress(list_of_elements):
time.sleep(0.2)
If you are using Python 3
then this is for you and it really works.
print(value , sep='',end ='', file = sys.stdout , flush = False)
Just figured this out on my own for showing a countdown but it would also work for a percentage.
import time
#Number of seconds to wait
i=15
#Until seconds has reached zero
while i > -1:
#Ensure string overwrites the previous line by adding spaces at end
print("\r{} seconds left. ".format(i),end='')
time.sleep(1)
i-=1
print("") #Adds newline after it's done
As long as whatever comes after '/r' is the same length or longer (including spaces) than the previous string, it will overwrite it on the same line. Just make sure you include the end='' otherwise it will print to a newline. Hope that helps!
for object "pega" that provides StartRunning(), StopRunning(),
boolean getIsRunning() and integer getProgress100() returning
value in range of 0 to 100, this provides text progress bar
while running...
now = time.time()
timeout = now + 30.0
last_progress = -1
pega.StartRunning()
while now < timeout and pega.getIsRunning():
time.sleep(0.5)
now = time.time()
progress = pega.getTubProgress100()
if progress != last_progress:
print('\r'+'='*progress+'-'*(100-progress)+' ' + str(progress) + "% ", end='', flush=True)
last_progress = progress
pega.StopRunning()
progress = pega.getTubProgress100()
print('\r'+'='*progress+'-'*(100-progress)+' ' + str(progress) + "% ", flush=True)