How to create a spinning command line cursor?
Something like this, assuming your terminal handles \b
import sysimport timedef spinning_cursor(): while True: for cursor in '|/-\\': yield cursorspinner = 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 sysimport timeimport threadingclass 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, sysspinner = 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