13

I'm writing a progress bar as this How to animate the command line? suggests. I use Pycharm and run this file in Run Tool Window.

import time
def show_Remaining_Time(time_delta):
    print('Time Remaining: %d' % time_delta, end='\r', flush=True)

if __name__ == '__main__':
    count = 0
    while True:
        show_Remaining_Time(count)
        count += 1
        time.sleep(1)

However, the code displays nothing if I run this .py file. What am I doing wrong?


I tried Jogger's suggest but it's still not working if I use print function.

However the following script works as expected.

import time
import sys
def show_Remaining_Time(time_delta):
    sys.stdout.write('\rtime: %d' % time_delta) # Doesn't work if I use 'time: %d\r'
    sys.stdout.flush()
if __name__ == '__main__':
    count = 0
    while True:
        show_Remaining_Time(count)
        count += 1
        time.sleep(1)

I have 2 questions now:

  1. Why stdout works but print() not.

  2. Why the How to animate the command line? suggests append \r to the end while I have to write it at the start in my case?

Community
  • 1
  • 1
spacegoing
  • 5,056
  • 5
  • 25
  • 42
  • 1
    Works fine for me in the interactive interpreter. Are you running in a weird shell by any chance, say, the IDLE shell? – ShadowRanger Jan 09 '16 at 05:34
  • @ShadowRanger I'm running it with Pycharm's Run Tool Window. If I don't pass `end='\r'` it prints as normal. But I want to keep updating the same line. – spacegoing Jan 09 '16 at 05:36
  • Yeah, PyCharm's run window isn't a normal terminal. It doesn't handle carriage returns the way you might want. Run in a normal command prompt. – ShadowRanger Jan 09 '16 at 05:47
  • 2
    Hmm... If that works, Jorge might be right; PyCharm must erase on carriage return. `print` would work, but you'd be doing: `print('\rTime Remaining: %d' % time_delta, end='', flush=True)` instead (so the carriage return is printed first, not last). – ShadowRanger Jan 09 '16 at 05:50
  • @ShadowRanger Yes it works! Have to pass `end=''` otherwise it won't work neither. – spacegoing Jan 09 '16 at 05:54
  • I did include the `end=''` in there for a reason; the default value is `end="\n"` (which translates to `os.linesep` automatically), which would have caused a new line and undone the intent of the carriage return. – ShadowRanger Jan 09 '16 at 06:03

2 Answers2

5

The problem is that the '\r' at the end clears the line that you just printed, what about?

import time
def show_Remaining_Time(time_delta):
    print("\r", end='')
    print('Time Remaining: %d' % time_delta, end='', flush=True)

if __name__ == '__main__':
    count = 0
    while True:
        show_Remaining_Time(count)
        count += 1
        time.sleep(1)

In this way, you clear the line first, and then print the desired display, keeping it in screen for the duration of the sleep.

NOTE: The code above was modified to add the end='' as suggested in the comments for the code to work properly in some platforms. Thanks to other readers for helping to craft a more complete answer.

Jorge Torres
  • 1,426
  • 12
  • 21
  • 2
    On most terminals I'm aware of `\r` doesn't clear anything. It moves the cursor, but further output is needed to overwrite what is there. Also, you're not disabling the automatic new line for either of your prints, so the net effect is to print every output on a new line; the explicit `'\r'` `print` does nothing. – ShadowRanger Jan 09 '16 at 05:47
  • Other problems aside (as not using end=''), this did the trick for me. – arielnmz May 14 '17 at 22:34
  • I had to use `print('\r', end='')` and `print('output', end='', flush=True)` to make this work the way I expected. Thanks for the good starting point though! – Daniel Buckmaster Nov 02 '17 at 14:14
0

This method can print in the same command line:

import time
def show_Remaining_Time(time_delta):
     print(' \r%d:Time Remaining' % time_delta, end = '',flush=False)

if __name__ == '__main__':
    count = 0
    while True and count < 10:
        show_Remaining_Time(count)
        count += 1
        time.sleep(1)
Scott Severance
  • 943
  • 10
  • 27
jayasri
  • 9
  • 1