Search code examples
pythoncoding-stylejythonargparseoptparse

Python: how to write code that looks nicely and works with argparse or optparse?


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?


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"])