2

I have a project that uses Python (2.* flavors) extensively and I am wondering if there is a terminal menu library or something to that effect? I am looking to breathe some flavor and life into my script by simplifying some of the options using arrow key highlightable options, some color, etc etc. I vaguely recall there being a way to make a bash shell terminal menu but I'm not at all sure how I would pass user input from bash to the python script, perhaps have a bash terminal menu push the script call with sysarggs? I'd like something on the python side if possible. Any suggestions?

Also just a random question, kind of fits in here since we're on the topic of terminal aesthetics, what's the best way to handle a counter? My script looks for image files, then when it finds one it clears the terminal with a subprocess call to clear and then prints the total images found again IE 10 images, find one, clear, print "11 images found", sometimes my script works REAL fast and I feel this detriments performance. Thoughts?

Thanks so much everyone, I love stack overflow ;)

Edit - Thanks for all the quick responses! I have alot of options to mull over. I gave everyone an upvote because all of your responses are helpful. I will check out all the libraries when I get home and try to pick one of you for an answer depending on what hashes out the best, wish I could pick you all though because all of your answers are relevant! Much appreciated folks. I'll report back in once I get home from work and get a chance to get some coding in ;)

Edit 2 - A clarification on the counter/progress display, looking for a way to keep this from detrimenting performance when my script finds thousands of images in a very short ammount of time, this is real chopped up python...

for each item in list:
    if item ends with .jpg
        cnt=cnt+1
        do stuff with image file
        subprocess.call('clear')
        print str(cnt)+" total images processed."

Thanks again!

0xhughes
  • 2,703
  • 4
  • 26
  • 38
  • I don't understand what you're asking in the counter part. – Matthew Adams Dec 03 '12 at 16:00
  • @MatthewAdams Hey, sorry for the vagueness! Basically everytime my script finds an image file from whatever source it's looking at, it does a quick cnt = cnt+1, thus upping the counter. So basically the counter/progress display goes a little like - Refer to edit 2! – 0xhughes Dec 03 '12 at 19:18
  • Ah. It's hard to talk about performance hits when "do stuff with image file" is definitely the slowest part of that. I guess you could try to do it in parallel if you want. – Matthew Adams Dec 03 '12 at 20:02
  • @MatthewAdams It's looping through a file list, if the file name ends with jpg, it pushes that file name to another list. So do stuff is this, "mylist.append(item)". The ACTUAL processing of the item happens later. Like I said, chopped up python ;) – 0xhughes Dec 03 '12 at 20:16
  • Oh then there's nothing really slow there, though clearing the screen every time seems totally unnecessary. – Matthew Adams Dec 03 '12 at 21:27

3 Answers3

5

Check out Clint (*C*ommand *L*ine *IN*terface *T*ools)!

Example colors:

from clint.textui import colored

print 'I love ' + colored.yellow('pyt') + colored.blue('hon')

and indents too:

from clint.textui import colored, indent, puts

with indent(3, quote=colored.red(' >')):
    puts ('some random text')
    puts ('another text')
    with indent(3, quote=colored.green(' |')):
        puts('some more nested identation')
        puts('cool isn\'t?')

P.S. The same author wrote a similarly nice HTTP request library called "requests": https://github.com/kennethreitz/requests

dkamins
  • 21,450
  • 7
  • 55
  • 59
4

If you want a lot of control and you're on *nix, you could use the stdlib curses module.

If you just want a bit of color (/don't want to modify your script a ton to fit curses), you can use ANSI escape codes. For example:

print '\033[1;32mgreen\033[1;m'

will print the word 'green' colored... green.

Here's a loading bar I came up with using carriage returns (based on the answers in this forum):

from time import sleep 
import sys 

num = 100

print 'Loading: [%s] %d%%' % (' '*(num/2), 0),

try:
    colorCode = 43
    for x in xrange(num+1):
        if x == num: colorCode = 42
        print '\rLoading: [\033[1;%dm%s\033[1;m%s] %d%%' % (colorCode, "|"*(x/2), " "*(num/2-x/2), x), 
        sys.stdout.flush()
        sleep(0.02) # do actual stuff here instead 
except KeyboardInterrupt:
        print '\rLoading: [\033[1;41m%s\033[1;m%s] %d%%  ' % ("|"*(x/2), " "*(num/2-x/2), x)

Example Output:

Loading: [|||||||||||||||||||||||||||||||||||||||||         ] 82%

(Although it doesn't show up on SO, it is colored- yellow for loading, red for abort, and green for done.)

Matthew Adams
  • 9,426
  • 3
  • 27
  • 43
2

There's a library called Urwid that offers menus and some more. I never used it for serious purposes, but the it work pretty fine with my preliminary experiences on it. It works on Un*x systems only though. (The project page says it works under Cygwin, but I never tried.)

uranusjr
  • 1,380
  • 12
  • 36
  • 1
    I've never tried `curses`, but Urwid offers a run loop with signals/callbacks, both of which you need to setup manually with `curses` AFAIK. This is huge for someone more familiar with GUI frameworks, like myself. – uranusjr Dec 03 '12 at 18:46
  • Urwid has the menus (droids) i'm looking for ;) @uranusjr – 0xhughes Dec 21 '12 at 03:08