python contextmanagers, subprocesses, and an ascii spinner

I have a command line script that takes too long to run. I profiled the script and the problem is in some fairly complex third-party code. So instead of fixing that stuff, I’m going to distract users with a pretty ascii spinner.

Run this script to see the spinner in action (you’ll have to kill the process afterward):

$ cat spin_forever.py
# vim: set expandtab ts=4 sw=4 filetype=python:

import sys, time

def draw_ascii_spinner(delay=0.2):
for char in '/-\\\\|': # there should be a backslash in here.
sys.stdout.write(char)
sys.stdout.flush()
time.sleep(delay)
sys.stdout.write('\\\\r') # this should be backslash r.

while "forever":
draw_ascii_spinner()

Next I made a context manager (this is the name of the things you use with the new python “with” keyword) that uses the subprocess module to fork off another process to run the spinner:

$ cat distraction.py
# vim: set expandtab ts=4 sw=4 filetype=python:

import contextlib, subprocess, time

@contextlib.contextmanager
def spinning_distraction():
p = subprocess.Popen(['python', 'spin_forever.py'])
yield
p.terminate()

Finally I added my new context manager to the code that takes so long to run:

def main():

with spinning_distraction():
time.sleep(3) # pretend this is real work here.

if __name__ == '__main__':
main()

If you’re following along at home, you can run python distraction.py and you’ll see the spinner go until the main application finishes sleeping.

The main thing I don’t like is how I’m using an external file named spin_forever.py. I don’t want to worry about the path to where spin_forever.py lives. I would prefer to use some function defined in a module that I can import.

Published by

matt

My name is Matt Wilson and I live in Cleveland Heights, Ohio. I love random emails from strangers, so get in touch! matt@tplus1.com.

  • Sounds like the multiprocessing module might be useful to you. You can use it to run a function in a subprocess.

  • I just read about it, and yeah, it is much nicer. Thanks!

  • Hey Matt, I wrote a response to this post on my website. I wrote it in a threaded formation rather than by using Popen. You can find it here: http://www.evanfosmark.com/2009/07/single-proce

  • I really like your solution! I'm going to rewrite my original one to
    use multiprocessing instead, so that I don't need to worry about the
    path to the external script.

    Matt

  • Hello all,
    Can sonone tell me that what is the function of ts=4 sw=4 in the below linw of the code.
    I did not know whats the funtion of it.Please help me in this matter.
    # vim: set expandtab ts=4 sw=4 filetype=python:

  • That line is a comment, so python ignores it. My text editor uses
    that line to set some options. Read up on vim modelines if you are
    really interested.

    The important thing to remember is that python ignores comments, so
    that line has no effect on the program.

  • thanks for sharing

  • Very nice puthon post

  • I really like your solution! I'm going to rewrite my original one to
    use multiprocessing instead, so that I don't need to worry about the
    path to the external script.

  • I digged this for more news from you.

    Thanks
    FERMINA NEIDA
    ______________________________________________

  • You got a nice blog up there.

  • You got a nice blog up there.