How to create a spinning command line cursor?

Is there a way to print a spinning cursor in a terminal using Python?


Something like this, assuming your terminal handles \b

import sys
import time

def spinning_cursor():
    while True:
        for cursor in '|/-\\':
            yield cursor

spinner = spinning_cursor()
for _ in range(50):
    sys.stdout.write(next(spinner))
    sys.stdout.flush()
    time.sleep(0.1)
    sys.stdout.write('\b')

Easy to use API (this will run the spinner in a separate thread):

import sys
import time
import threading

class Spinner:
    busy = False
    delay = 0.1

    @staticmethod
    def spinning_cursor():
        while 1: 
            for cursor in '|/-\\': yield cursor

    def __init__(self, delay=None):
        self.spinner_generator = self.spinning_cursor()
        if delay and float(delay): self.delay = delay

    def spinner_task(self):
        while self.busy:
            sys.stdout.write(next(self.spinner_generator))
            sys.stdout.flush()
            time.sleep(self.delay)
            sys.stdout.write('\b')
            sys.stdout.flush()

    def __enter__(self):
        self.busy = True
        threading.Thread(target=self.spinner_task).start()

    def __exit__(self, exception, value, tb):
        self.busy = False
        time.sleep(self.delay)
        if exception is not None:
            return False

Now use it in a with block anywhere in the code:

with Spinner():
  # ... some long-running operations
  # time.sleep(3) 

A nice pythonic way is to use itertools.cycle:

import itertools, sys
spinner = itertools.cycle(['-', '/', '|', '\\'])
while True:
    sys.stdout.write(next(spinner))   # write the next character
    sys.stdout.flush()                # flush stdout buffer (actual character display)
    sys.stdout.write('\b')            # erase the last written char

Also, you might want to use threading to display the spinner during a long function call, as in http://www.interclasse.com/scripts/spin.php


A solution:

import sys
import time

print "processing...\\",
syms = ['\\', '|', '/', '-']
bs = '\b'

for _ in range(10):
    for sym in syms:
        sys.stdout.write("\b%s" % sym)
        sys.stdout.flush()
        time.sleep(.5)

The key is to use the backspace character '\b' and flush stdout.