Question

I have to parse arguments so I used argparse module. This works well with Python 3.3 and Python 2.7. But some time I have to use it with Jython, and the last stable version of Jython is 2.5.3. This version do not have argparse module so I used older optparse module:

args = None
try:
    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument("-u", "--url", action="store", dest="url", default=url, help='test script URL like "http://127.0.0.1/isof/hdb_ver_xml.hdb" or "hdb://127.0.0.1/isof/hdb_ver_xml.hdb"')
    parser.add_argument("-t", "--threads", action="store", type=int, dest="threads_cnt", default=threads_cnt, help='threads count')
    parser.add_argument("-T", "--timeout", action="store", type=int, dest="timeout_minutes", default=timeout_minutes, help='timeout in minutes')
    args = parser.parse_args()
except:
    import optparse
    parser = optparse.OptionParser()
    parser.add_option("-u", "--url", action="store", dest="url", default=url, help='test script URL like "http://127.0.0.1/isof/hdb_ver_xml.hdb" or "hdb://127.0.0.1/isof/hdb_ver_xml.hdb"')
    parser.add_option("-t", "--threads", action="store", type=int, dest="threads_cnt", default=threads_cnt, help='threads count')
    parser.add_option("-T", "--timeout", action="store", type=int, dest="timeout_minutes", default=timeout_minutes, help='timeout in minutes')
    args, _ = parser.parse_args()
return args

For me this code looks ugly because any change must be in 2 places. Of course I can use something like:

OPT_THREADS_HELP = 'threads count'
...
... help=OPT_THREADS_HELP

which will help a little but maybe there is nicer way of writing such code. Any idea?

Was it helpful?

Solution

Have you considered storing your arguments separately?

 args = [{"args":("-u", "--url"), 
          "kwargs": {"action": "store", "dest": "url", "default": url, 
                     "help": 'test script URL like "http://127.0.0.1/isof/hdb_ver_xml.hdb" or "hdb://127.0.0.1/isof/hdb_ver_xml.hdb"'}
         }, ...]

Then whichever library you use, you can call:

try:
    import argparse
    parser = argparse.ArgumentParser()
    for arg in args:
        parser.add_argument(*arg['args'], **arg['kwargs'])
except:
    import optparse
    parser = optparse.OptionParser()
    for arg in args:
        parser.add_option(*arg['args'], **arg['kwargs'])

You could simplify further, allowing you to reduce the code in the try block, by using the bound method separately:

try:
    import argparse
except ImportError:
    import optparse
    parser = optparse.OptionParser()
    add_func = parser.add_option
else:
    parser = argparse.ArgumentParser()
    add_func = parser.add_argument

for arg in args:
    add_func(*arg["args"], **arg["kwargs"])

OTHER TIPS

If you don't mind using a 3rd party library, I would suggestion you try docopt:

That how you do thing there:

"""Naval Fate.

Usage:
  naval_fate.py ship new <name>...
  naval_fate.py ship <name> move <x> <y> [--speed=<kn>]
  naval_fate.py ship shoot <x> <y>
  naval_fate.py mine (set|remove) <x> <y> [--moored | --drifting]
  naval_fate.py (-h | --help)
  naval_fate.py --version

Options:
  -h --help     Show this screen.
  --version     Show version.
  --speed=<kn>  Speed in knots [default: 10].
  --moored      Moored (anchored) mine.
  --drifting    Drifting mine.

"""
from docopt import docopt


if __name__ == '__main__':
    arguments = docopt(__doc__, version='Naval Fate 2.0')
    print(arguments)

See docopt

docopt is tested with Python 2.5, 2.6, 2.7, 3.2, 3.3 and PyPy.

Docopt is also successfully used with Jython!

Your best option is to stick to just one command-line argument parsing library.

optparse is still available in Python 3.3 and 3.4, and no announcement has been made yet when it will be removed, if ever. Yes, it is deprecated and won't receive new versions, but it still works just fine.

When you need to support such a wide range of Python versions, don't try to duplicate work. If your needs are met by optparse, use just optparse.

You can just assign the parser class to a variable and monkey patch OptionParser to have add_argument.

Like this:

try:
    import argparse
    Parser = argparse.ArgumentParser
except ImportError:
    import optparse
    Parser = optparse.OptionParser
    Parser.add_argument = Parser.add_option


parser = Parser()
parser.add_argument("-u", "--url", action="store", dest="url", default=url, help='test script URL like "http://127.0.0.1/isof/hdb_ver_xml.hdb" or "hdb://127.0.0.1/isof/hdb_ver_xml.hdb"')
parser.add_argument("-t", "--threads", action="store", type=int, dest="threads_cnt",default=threads_cnt, help='threads count')
parser.add_argument("-T", "--timeout", action="store", type=int, dest="timeout_minutes", default=timeout_minutes, help='timeout in minutes')

args, _ = parser.parse_args()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top