5

This code works as expected. Output:

Loading 
Loading.
Loading..
Loading...

Code:

done = False
count = 0

while not done:
    print '{0}\r'.format("Loading"),
    time.sleep(0.25)
    print '{0}\r'.format("Loading."),
    time.sleep(0.25)
    print '{0}\r'.format("Loading.."),
    time.sleep(0.25)
    print '{0}\r'.format("Loading..."),
    time.sleep(0.25)
    count += 1
    if count == 5:
        done = True

And this code doesn't. Output:

Loading.
Loading...

Code:

done = False
count = 0

while not done:
    print '{0}\r'.format("Loading"),
    time.sleep(0.125)
    print '{0}\r'.format("Loading."),
    time.sleep(0.125)
    print '{0}\r'.format("Loading.."),
    time.sleep(0.125)
    print '{0}\r'.format("Loading..."),
    time.sleep(0.125)
    count += 1
    if count == 5:
        done = True

Why does the time function seem to skip every second print statement if it is lower than 0.25?

Mike Müller
  • 82,630
  • 20
  • 166
  • 161
Gunnm
  • 974
  • 3
  • 10
  • 21
  • 3
    Strange, it works on my machine. Maybe it's OS-dependent. I'm on Windows 7. What operating system are you on? – Kevin Jan 06 '16 at 13:00
  • 3
    I don't have this problem, I get `Loading Loading. Loading.. Loading...`, but it's likely to do with your carriage returns. – SuperBiasedMan Jan 06 '16 at 13:00
  • I'm using PyCharm and Windows 10 – Gunnm Jan 06 '16 at 13:01
  • 2
    It seems to be related to output buffering and the effects will vary a lot on different machines. It didn't print anything at all on my machine, for example. :-) – Lav Jan 06 '16 at 13:03
  • I'm just getting `>>> ing...` :( – Jasper Jan 06 '16 at 13:13
  • http://stackoverflow.com/questions/32233636/command-prompt-cant-write-letter-by-letter/32233850#32233850 – Padraic Cunningham Jan 06 '16 at 13:21
  • Update: yep, it's output buffering indeed. So essentially this is a duplicate of http://stackoverflow.com/questions/107705/disable-output-buffering – Lav Jan 06 '16 at 13:25
  • 3
    If you import the print function or switch to Python 3, you can just use `flush=True` instead of making explicit calls to `sys.stdout.flush()`. – TigerhawkT3 Jan 06 '16 at 13:37
  • @TigerhawkT3 that's good tip thanks! – Gunnm Jan 06 '16 at 14:07
  • 2
    @TigerhawkT3: You can't use the `__future__` import to get `flush=True` support in Py2; the `flush` argument was only added to the `print` function in Py 3.3, and never backported to the 2.x line. – ShadowRanger Jan 06 '16 at 14:23
  • Tested and got `TypeError`... looks like you're quite right. That's too bad. :( – TigerhawkT3 Jan 06 '16 at 14:26

1 Answers1

5

Reason

Depending on the platform, Python buffers the output to different degrees. For example, on Mac OSX there is no output at all even for your version with 0.25 seconds sleep.

Flushing manually

Flushing manually should work:

import sys
import time

done = False
count = 0

while not done:
    for n in range(4):
        print '{0}\r'.format("Loading" + n * '.'),
        sys.stdout.flush()
        time.sleep(0.125)
    print ' ' * 20 + '\r',
    count += 1
    if count == 5:
        done = True

You need to flush the output with sys.stdout.flush(). You also need to print empty spaces to make the dots "going back and forth":

print ' ' * 20 + '\r',

More minimal and cleaned up

This is shortened and a bit more general in terms of the shown text:

import sys
import time


text = 'Loading'
for _ in range(5):
    for n in range(4):
        print '{0}\r'.format(text + n * '.'),
        sys.stdout.flush()
        time.sleep(0.25)
    nspaces = len(text) + n
    print ' ' * nspaces + '\r',

Running unbuffered from the commandline

You can remove the line:

sys.stdout.flush()

if you run your script with the -u option:

python -u script_name.py

Note: This will have an effect on all print statements.

Mike Müller
  • 82,630
  • 20
  • 166
  • 161
  • 1
    Instead of printing 20 spaces it might be cleaner to use the terminal size: `width = struct.unpack('HHHH', fcntl.ioctl(0, termios.TIOCGWINSZ, struct.pack('HHHH', 0, 0, 0, 0)))[1]` – ThiefMaster Jan 06 '16 at 13:47
  • 1
    @ThiefMaster Looks pretty complicated to me. Isn't `print ' ' * nspaces + '\r',` a bit simpler? I use it my cleaned-up version. – Mike Müller Jan 06 '16 at 13:53
  • 1
    hrm yeah, in this case it's easier for sure. In a real application you'd put it as a `term_size` function in a util module or even provide a `clear_line()` function that prints \r and the right number of spaces – ThiefMaster Jan 06 '16 at 13:54
  • It doesn't work in PyCharm but it works in Python so it should be fine. Thank you for help and explaining this to me. – Gunnm Jan 06 '16 at 14:07