Tips for a *nix python cli - Programming On Unix

Users browsing this thread: 7 Guest(s)
venam
Administrators
Hello *nixer,
In this thread I'll give some tips for doing a python cli program. Feedbacks and comments are highly appreciated.

[*]Taking program arguments:
Users normally expect to be able to directly give the program arguments from the command line and to receive help when adding the -h or --help argument.
One way of doing that would be to parse the argc and argv. To do that you'll need to import sys. This method is more of a waste of time then anything else.
A better way of doing that would be to use the module optparse. It handles the help, the long arguments, and the short arguments.
Here's an example using optparse:
Code:
#!/usr/bin/env python
import optparse
def main():
    p = optparse.OptionParser()
    p.add_option('--person', '-p', default="world")
    options, arguments = p.parse_args()
    print 'Hello %s' % options.person

if __name__ == '__main__':
    main()

You can also find it here: https://paste.xinu.at/49o/
Here's an example of the output of the above program:
Code:
raptor ~ $ python2 python_cli.py --help                                                <
Usage: python_cli.py [options]

Options:
  -h, --help            show this help message and exit
  -p PERSON, --person=PERSON

[*]Tab completion:
Tab completion can be really nifty and adds a *nix feel to the program. If you search around the internet you won't find a lot of answers on how to do it. Here's a module https://raw.github.com/venam/badaboum/ma...mpleter.py that you can change as desired that when added to the program as followed makes tab completion work when taking the user's input.
Code:
import readline,completer

self.comp = completer.Completer()
readline.set_completer_delims(' \t\n;')
readline.parse_and_bind("tab:complete")
readline.set_completer(self.comp.complete)

[*]Creating a prompt/terminal-like/interpreter:
Some people might want to take things a step forward and create a prompt/terminal-like environment in their program. I mean something similar to the python interpreter, meterpreter, gdb, etc.. It is fairly easy to accomplish. All you have to do is play around with the tab completion and make it change how it completes depending of which part of the program the user is in. (State Pattern)

[*]Adding a choice between cli and curses:
Curses interfaces are not cli but they can give the program a feeling of completeness. There's many hard way of creating curses interfaces like using the curses module. To not loose some neurons along the way use the urwid module http://excess.org/urwid/tutorial.html. It helps creating curses as if the components were like the one of a GUI-like (text-box,button,label,etc..).

That's it! May the force be with you.
gurhush
Long time nixers
Extremely useful. Thanks for the share, venam.
venam
Administrators
Someone (Rahmu from Lebgeeks) told me that optparse is deprecated and to use argparse instead (https://docs.python.org/dev/library/argparse.html) or docopt (http://docopt.org/).
b4dtR1p
Members
optparse it's old, powerfull and *nix style!
for me is the best choise for cli tools
░ ░░▒░ ░ ░ ░ ▒ ░ ░▒ ▒░

░ ░ ░ ░ ░
projektile
Members
hey this is awesome. i never knew python supported tab completion. 10/10.
ashen
Members
configargparse (https://github.com/bw2/ConfigArgParse) is pretty nifty. It lets you have a config file to set default arguments as well, if you've got a more complex program

tdryer/hangups uses it, and it's a fairly nice piece of software
venam
Administrators
Ah, this thread.


(14-09-2015, 08:45 PM)ashen Wrote: configargparse (https://github.com/bw2/ConfigArgParse) is pretty nifty. It lets you have a config file to set default arguments as well, if you've got a more complex program
That's a nice simple library.

I would also like to add that if you use ZSH you could write a completion script in "/usr/share/zsh/functions/Completion/Unix/".

It's not complicated, here's a stupid example.
darthlukan
Members
To add on to the tips, here's a snippet I tend to use quite a bit for when I want my utilities to use notifications. The docs for notify2 are a bit wonky due to all of the possibilities, but if you just want a simple notification integration function, here it is:

Code:
import notify2

    ...

    def note_set_and_send(app, summary):
    """
    Creates a DBUS notification.
    """
    notify2.init('Pounce: ')
    return notify2.Notification(app, summary).show()

For an example of this in practice, you can see this silly utility that I wrote when I was first learning to program (a few years ago): https://github.com/darthlukan/pounce
Github: https://github.com/darthlukan
CRUX Ports: http://ports.brianctomlinson.com
GPG: 3694569D
"We're all human, act accordingly." -- Me
venam
Administrators
(15-09-2015, 02:18 AM)darthlukan Wrote: To add on to the tips, here's a snippet I tend to use quite a bit for when I want my utilities to use notifications. The docs for notify2 are a bit wonky due to all of the possibilities, but if you just want a simple notification integration function, here it is:

Code:
import notify2

    ...

    def note_set_and_send(app, summary):
    """
    Creates a DBUS notification.
    """
    notify2.init('Pounce: ')
    return notify2.Notification(app, summary).show()
For an example of this in practice, you can see this silly utility that I wrote when I was first learning to program (a few years ago): https://github.com/darthlukan/pounce
The problem with notification is that they aren't really for CLI.
darthlukan
Members
Yeah, there is an assumption that while you're executing via cli, you're working in something that makes sense to receive a notification, like a WM. I use that snippet when I run background jobs that I want to be alerted about, so to me, it's useful. I only shared it here as it seemed appropriate at the time.
Github: https://github.com/darthlukan
CRUX Ports: http://ports.brianctomlinson.com
GPG: 3694569D
"We're all human, act accordingly." -- Me
ki113d
Members
Not really anything to do with cli applications, but great for rapid development: Bpython utilises urwid to create an amazingly clean interpreter that offers not only proper tab completion, an expected parameter list and upload to pastebin functionality, but also syntax highlighting, the ability to rewind your input and much more.

In my opinion, bpython is almost an essential piece of software for any python developer who enjoys both functionality and an aesthetically pleasing interface.
venam
Administrators
I wrote a template that regroups a lot of what was said in this thread.
You can find it here.

Contributions are welcome, don't be shy!