1

I'm writing a CLI application in python with is used by means of a rather elaborate commandline language. The idea is very similar to find(1) which arguably has the same property.

Currently, the parser is completely handwritten using a handmade EBNF description language. The problem is that this language is very awkward to use because I have to write everything as python structures. I also feel that my program is still way too bloated because of the parsing.

Is there any lib that features ease of use, and a true description language (input as string/document) for commandline parsing? From the syntax tree, I would like to directly map each item to a class instance. Naturally, I don't want a tokenizer, or at least the tokenizer must map straight from commandline arguments to tokens.

Thanks for all suggestions!

UPDATE: The whole point of my program is to generate objects and pass them through any number of filters (possibly unpure/effectful actions) that might or might not output the objects again, or might even output objects of another type. The general idea is obviously gleaned from find(1). An example commandline would be:

~/picdb.py -sqlselect 'select * from pics where dirname like "testdir%"' -tagged JoSo  -updateFromFile [ -resx +300 -or -resX +200 -resY +500 ] -printfXml '<jpegfile><src>%fp</src><DateTimeOriginal>%ed</DateTimeOriginal><Manufacturer>%eM</Manufacturer><Model>%em</Model></jpegfile>%NL'
4
  • 2
    Would argparse (python 2.7+) suit your needs? Commented Apr 28, 2012 at 14:00
  • In addition to the comment by @Aufwind -- You don't need to have python 2.7 or newer to user argparse. It works just fine with older versions of python -- you just have to install if yourself (as opposed to being included in the standard library). Commented Apr 28, 2012 at 15:52
  • I think that if you described your commandline (or at least gave an example or two), we might be able to see if this is a candidate for argparse/optparse ... Commented Apr 28, 2012 at 15:53
  • @mgilson: Thanks, good point, I'll update my post and expect better answers instead of only counter-questions :) Commented Apr 28, 2012 at 16:20

2 Answers 2

3

This is a very tricky problem...You can "bind" actions to commandline arguments using argparse quite easily (e.g. create a class, operate on a previously created class ...). Here's a silly example of that...(argument --foo creates an object, argument --bar modifies the object created by --foo).

from argparse import ArgumentParser,Action

class Foo(object):
    def __init__(self,*args):
        self.args=args
    def __str__(self):
        return str(self.args)

class FooAction(Action):
    def __call__(self,parser,namespace,values,option_string=None):
        setattr(namespace,self.dest,Foo(*values))  #Add Foo to the options...
class BarAction(Action):
    def __call__(self,parser,namespace,values,option_string=None):
        FooObj=getattr(namespace,'foo')  #raises an error if foo isn't in namespace...
                                         #In this way, BarAction is like a filter on the
                                         #object created by foo.
        FooObj.args=tuple(list(FooObj.args)+list(values)) #append to the list of args.

parser=ArgumentParser()
parser.add_argument('--foo',nargs='*',action=FooAction,help="Foo!")
parser.add_argument('--bar',nargs='*',action=BarAction,help="Bar! : Must be used after --foo")

namespace=parser.parse_args("--foo Hello World --bar Nice Day".split())
print (namespace)
print (namespace.foo)

However, this is a little different from yours in that -argument is not really possible with argparse, only -a or --argument. That may already be a deal breaker for you, I'm not sure...

The next difficulty is dealing with the brackets... [ and ]. If you can treat those as arguments to a different commandline option, you might be OK...You might be able to set up a second parser to parse out the inside portions -- but I've never tried anything like that before... (If anyone else has any ideas about how to deal with the brackets, I'd be very interested to hear them).

As far as optparse and getopt are concerned, I'm pretty sure that anything you can do with them, you can do with argparse, which is why I've left them out of the discussion.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much for your effort. That means that probably I'll stay with my handmade solution.
1

There are al least three modules you could try; argparse, optparse (deprecated in 2.7) and getopt. See chapter 15 of the Python standard library manual.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.