Reputation: 16691
Im trying to get the following output from a while loop to show the progress.
- ########
Below is the code,
print ' - #',
x = 1
while x < 15:
print '#',
time.sleep(0.5)
x += 1
But Im just getting all of the hashs printed once the while loop is complete (?)
Any ideas
Upvotes: 2
Views: 4147
Reputation: 2003
There are plenty of methods to this.
If you are working with Python 2.X, you need to call sys.stdout.flush()
after every print.
If you are using python 3 then you can get it done by doing
print(#,sep = ' ', flush=True)
You can disable the buffering completely if you run python with -u option: python -u script.py
If you run your script directly i.e. ./script.py
then specify it in the shebang line: #!/usr/bin/env python -u
.
The other way to do it is to set env variable PYTHONUNBUFFERED
from the bash shell:
export PYTHONUNBUFFERED="aa"
Adding more details to cause of the issue:
Stdout in Python is line buffered. Meaning if you had skipped the "," in your print your output will be printed as expected. But when the output is printed in the same line then it will be flushed only if there is a new line or the buffer is full. In case you redirect your output to a file instead of terminal (python script.py >output
), output will be flushed only when the buffer is full. This can be verified if you pipe the output to cat:
python script.py | cat
In all the methods mentioned in this answer and other answers we are explicitly telling Python to not buffer but flush the output as soon as it gets it.
More research on the topic:
This behavior is not Python Specific. This is the case with printf
in C as well. It is due to glibc implementation of linux. The reasoning behind this behavior is efficiency. Because the output is buffered number of read and write operations are minimized. I found this article which gives a brief description of the same: Unix Buffering Delays
Upvotes: 4
Reputation: 20336
print
by default writes to stdout which is stored in sys.stdout
. Stdout is flushed when a new line is printed. Since you aren't printing the new line, the text isn't displayed until you do. You can, however, flush stdout yourself:
import sys
import time
print ' - #',
sys.stdout.flush()
x = 1
while x < 15:
print '#',
sys.stdout.flush()
time.sleep(0.5)
x += 1
You really don't need a while
loop. A for
loop would be shorter:
import sys
import time
print ' - #',
sys.stdout.flush()
x = 1
for _ in range(15):
print '#',
sys.stdout.flush()
time.sleep(0.5)
Upvotes: 2
Reputation: 4010
I think you already got your answer but in case you later want to overwrite the same line, add a carriage return \r
before the characters you're printing (to return your typewriter's carriage to the start of the current line, of course ;) ). I use this to have my file processing scripts write to the same line - each new line overwriting the last. Some fiddling with additonal white space is necessary if the new line is shorter than the previous.
Eg. to make a rotating loader thingy that's eventually replaced by a growing line of #
s:
import sys
import time
# rotating loader "animation"
# Ubuntu or the aptitude package manager uses something similar
x = 1
symbols = ["|", "/", "-", "\\"]
while x < 20:
x+=1
sys.stdout.write("\r" + symbols[x%len(symbols)])
sys.stdout.flush()
time.sleep(0.2)
# progress bar "animation" using hashtags
x = 1
sys.stdout.write("\r")
while x < 10:
x+=1
sys.stdout.write('#')
sys.stdout.flush()
time.sleep(0.2)
print("")
Upvotes: 2
Reputation: 9112
Have a look at tqdm. It displays for you a good looking progress bar very easily.
from tqdm import tqdm
for i in tqdm(range(9)):
...
Upvotes: 0
Reputation: 428
import sys
import time
while True:
sys.stdout.write('#')
sys.stdout.flush()
time.sleep(0.5)
Upvotes: 5