I’m not sure whether I’ve just reinvented the wheel, but … a new way of building command-line interface in Python!
Well, it probably won’t work for everything. Where it works at it’s best is when you have a number of modules, which meant to do something, and you don’t want to build the CLI interface to each of them. Say, in my case — I have 5 modules for the running various machine-learning tasks, which act as wrappers around various Java applications (written by me and third-party). Each module has a number of functions, which have something in common — they take input file(s), process it and write output to another file.
Now, let’s get to the code.
tagger.py - performs feature extraction and invokation of Mallet tagger
Actual code is not included — just methods’ names.
import os
import sysfrom common import *def extractFeaturesForTagger(filename, output, jrunner = None):
...def invokeTagger(featuresFile, modelFile, train = True, output = None, jrunner = None):
...def despatch(args):
if len(args) < 3:
return False cmd = args[2]
if cmd == 'fe':
try:
(ifile, ofile) = args[3:]
except:
return False extractFeaturesForTagger(ifile, ofile)
elif cmd == 'train':
try:
(ifile, ofile) = args[3:]
except:
return False invokeTagger(ifile, ofile)
elif cmd == 'tag':
try:
(fts, model, ofile) = args[3:]
except:
return False invokeTagger(fts, model, False, ofile)
else:
print("Couldn't recognise the options: ")
print(args)
return False return True
def describe():
return ("tagger", [
("fe", "[I]uafFile, [O]featureVectorsFile", "Extract features for tagger"),
("train", "[I]featureVectorsFile, [O]modelFile", "Train the model"),
("tag", "[I]featureVectorsFile, [I]modelFile, [O]taggerOutputFile", "Tag locations in file")
])
What matters is two functions - despatch and describe. First one actually takes standard sys.argv, assumes that it applies to current module and tries to apply the arguments to it’s functions. When it works, it invokes an appropriate method. When it’s not, it returns False.
Second method returns a tuple of string and list, which, in it’s turn consists of tuples of three elements — subcommand name, parameters and short description. Now when we have this module, let’s get to the despatcher.py:
#!/usr/bin/env python
# encoding: utf-8
"""
despatcher.pyCreated by Roman Kirillov on 2009-09-25.
Copyright (c) 2009 Yahoo! Inc. All rights reserved.
"""import sys
import osimport tagger
import disambiguatormodules = [tagger,disambiguator]def printHelp():
helpString = '\nUsage options: %s <module> <command> <command-specific-arguments>\n' % (sys.argv[0])
for m in modules:
(cmd, subcmds) = m.describe() helpString = helpString + '\n' + cmd + '\n' for scd in subcmds:
(s, params, descr) = scd
helpString = helpString + (s + "\t").rjust(15) # + params + " -- " + descr + "\n"
helpString = helpString + params + " -- " + descr + "\n" print(helpString)def canIHaz(val):
if not val:
printHelp()
sys.exit(3)def despatch():
if len(sys.argv) < 2 or sys.argv[1] == 'help':
printHelp()
sys.exit(0)
else:
for m in modules:
(cmd, subcmds) = m.describe()
if cmd == sys.argv[1]:
canIHaz(m.despatch(sys.argv))
if __name__ == '__main__':
despatch()
While it’s pretty easy to anyone who can read Python to understand, what’s this all about, let’s just show what happens when you run despatcher.py without parameters:
[kirillov@chiark integration]$ python despatcher.pyUsage options: despatcher.py <module> <command> <command-specific-arguments>tagger
fe [I]uafFile, [O]featureVectorsFile -- Extract features for tagger
train [I]featureVectorsFile, [O]modelFile -- Train the model
tag [I]featureVectorsFile, [I]modelFile, [O]taggerOutputFile -- Tag locations in filedisambiguator
fe [I]uafFile, [O]outputFileName, [I]useTaggedLocations (true/false) -- Invoke disambiguation feature extractor
import [I]featureVector, [O]malletImport -- Import feature vector to Mallet format
train [I]featureVector, [O]modelName -- Train disambiguators model
disambig [I]featureVector, [I]modelName, [O]output -- Run trained disambiguator over the feature vector
normalise [I]featureVector, [O]normalisedFeatureVector -- Normalises the feature vector
Pretty easy, huh? Of course, still needs a lot of tuning and polishing, but it feels so much better to have a centralised dispatcher, which takes care of printing help and handling options — rather than having a one for each module?
Posted via web from Roman’s blog | Comment »

Roman Kirillov
http://sigizmund.com
Posted via email from Roman’s blog | Comment »
Posted via email from Roman’s blog | Comment »
int a = 128; feature. Thanks again! Cheers, Posted via email from Roman’s blog | Comment »
Do you like “Edit in TextMate” command you can use in any Cocoa edit window, and write the text in your favourite text editor? (of course, TextMate that is). I like it too, and since I’ve switched to Firefox (after 1.5 years struggling with Safari and getting finally tired of it being SO slow sometimes!) I missed it a lot. Well, now you can do it, too – just follow the advice here: http://blog.circlesixdesign.com/2007/02/23/textmate-firefox/ Little tip: there’s no need to create any symbolic link, you can simply specify `/usr/local/bin/mate` as your editor, or, if you didn’t install `mate` command when installing TextMate (which I highly recommend to do), you can use `/Applications/TextMate.app/Content/MacOS/TextMate` to achieve nearly identical results.
Posted via email from Roman’s blog | Comment »
<p>Mesmerising Flash Application from Roman Kirillov on Vimeo.</p>
Try it yourself, really.
Posted via web from Roman’s posterous | Comment »
Posted via email from Roman’s posterous | Comment »

Main screen simply shows you the most important information – well, for me it’s not that bad, as the last bill was just yesterday and I am unlikely to put the needle to the left-most position. But, I can easily see what I want to, and that’s pretty much enough. You can also view your last bill summary, your recent charges (I found out how much one minute costs me when I’m in Spain!) – and even view your tariff details, which is something totally amazing if you need just a quick reference, on what you’re paying. Honestly, O2 - you did a great job and my congratulations are well-deserved!




See and download the full gallery on posterous
Grab it while it’s hot! (via O2 Blog)
Posted via email from Roman’s posterous | Comment »






Posted via email from Roman’s posterous | Comment »
I bet you’re surprised I do not look as smart as the rest of the guests (and not even nearly as smart as my beautiful wife). Well, that’s because I’ve been the most miserable person there – namely photographer, and spend the whole day jumping around with the camera (with two cameras, in fact), so at 12AM when guests were enjoying the Spanish wine and truly delicious food from the hotel’s restaurant, I fought myself to not fall asleep right where I was sitting.