8

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"

Xema
  • 1,796
  • 1
  • 19
  • 28
  • Have you seen this post? http://stackoverflow.com/questions/3160699/python-progress-bar – ma3oun Apr 20 '17 at 09:18
  • From the post you linked, I tried the tqdm approach. It is quite nice, but it is not working: the progress are written in successive lines. – Xema Apr 20 '17 at 09:35

1 Answers1

12

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)
jarzyn
  • 327
  • 2
  • 12
  • Thank you for your answer. However it didn't solve the problem (for me). The progress is shown in a new line, instead of overriding the previous progress (what I asked for). – Xema Jun 13 '17 at 14:39
  • What version of python and PyCharm are you using? I am working on python 2.7 and the 2017.1.3 PyCharm edition. – jarzyn Jun 13 '17 at 14:50
  • Python 3.6 and PyCharm 2016.3.2. Maybe I have to update my PyCharm ! – Xema Jun 13 '17 at 14:59
  • I've installed Python 3.6 and my code works as intended. Please update PyCharm and share if that resolves your problem. From what I remember after updating to 2017 there were some issues with projects created on v2016 so make sure you leave both version on you PC before you are certain that project will work on newer version. – jarzyn Jun 13 '17 at 15:18
  • I've tested it on PyCharm v2016.3 and code snippet works just fine. I even tried one of your solutions slightly modified: import time for i in range(10): print("\r"+str(i), end='', flush=True) time.sleep(0.1) Which work just fine. I am wondering if it is not connected to terminal settings. Maybie some bugged plugin? – jarzyn Jun 13 '17 at 21:51
  • 1
    Upvoted both this answer and [the other one](https://stackoverflow.com/a/44524810/2650249) as they helped me to get on the right track. To everyone saying it's not working: check if you are writing to `stdout` and NOT `stderr`! This snippet won't work when writing to PyCharm's `stderr` console (seems like it doesn't support carriage returns at all). Also, it is essential to put the carriage return at the beginning of the line and not at the end as then the console will swallow the line, not displaying anything. Other than that, worked like a charm, thanks! – hoefling Jan 14 '18 at 15:32