Reputation: 1886
My goal is to show a loading progress in my console by overwriting the previous line with the current progress. I have found plenty of solutions for version 3 of Python, but those are not working.
For instance:
import time
for i in range(10):
print(i, end='', flush=True)
time.sleep(1)
Gives me the following output:
0123456789
Or both:
import time
for i in range(10):
print(i, end='\r', flush=True)
time.sleep(1)
and:
import time
for i in range(10):
print("\b" + str(i), end='', flush=True)
time.sleep(1)
Gives me the following output:
0
1
2
3
...
Any idea ? I am working under PyCharm Community Edition with the Anaconda package.
Many thanks!
EDIT: the problem does not seem to happen when I run a python file (using PyCharm), but only when I do "Execute Selection in Console"
Upvotes: 8
Views: 8047
Reputation: 327
You need to get control over writing to stdout and flushing it. So link given by ma3oun is valuable answer. Unfortunately PyCharm console works differently than command line. Question how it works shall be directed to PyCharm team and maybe ask them to change this behaviour.
Anyway solution for your problem is to add \r
before you perform write:
import sys
import time
for i in range(10):
sys.stdout.write("\r{0}".format(str(i)))
sys.stdout.flush()
time.sleep(1)
However for shorter sleep time (for instance 0.1) there's a problem with flushing short buffer. For every flush you get more than just one write value printed. As a workaround I found that you can add another \r
like that:
for i in range(10):
sys.stdout.write("\r \r {0}".format(str(i)))
sys.stdout.flush()
time.sleep(0.1)
This will force console to display only one write value, but you will loose some of values in between display as it looks like refresh rate is slower than 0,1 of a second.
My solution for progress banner that is properly displayed in PyCharm console:
import sys
import time
progressVis = {0: ' ', 1: '- ', 2: '-- ', 3: '--- ', 4: '---- ', 5: '----- ',
6: '------ ', 7: '------- ', 8: '-------- ', 9: '--------- ', 10: '----------'}
size = 20
for i in range(0, size):
percent = int((float(i + 1) / size) * 10)
str1 = "\r \r [{0}] {1}/{2} {3}%".format(progressVis[percent],
i + 1, size,
((i + 1) * 100 / size))
sys.stdout.write(str1)
sys.stdout.flush()
time.sleep(0.1)
Upvotes: 12