Parsing Python arguments I'm trying to cover the following 4 scenarios:


No parameters
DB param
DB param and 1 option
No DB param and 1 option


So far I have the program working for all scenarios. However, I'm not happy with the way it's implemented. Is it possible to change this to a cleaner solution, rather than checking if there's only 1 parameter passed or catching an exception?

def do_work(database=None):
    if database:
        print 'Doing work for {0}'.format(database)
    else:
        print 'Doing work all database'

def do_other_work(database=None):
    if database:
        print 'Doing other work for {0}'.format(database)
    else:
        print 'Doing other work all database'

def create_parser():
    parser = ArgumentParser(description='Parser')
    parser.add_argument('--db', '-d', dest='database',
                        default=None, required=False, help='Database name')

    option_group = parser.add_mutually_exclusive_group(required=False)
    option_group.add_argument('-a', dest='cmd',
                              action='store_const',
                              const=lambda args: do_other_work(args.database)
    return parser

if len(sys.argv) == 1:
    do_work()

parser = create_parser()
parsed_args = parser.parse_args(sys.argv[1:])

try:
    parsed_args.cmd(parsed_args)
except TypeError:
    do_work(parsed_args.database)



No parameters passed: do_work() for all databases
db parameter passed and no option: do_work() for just that database
db parameter and an option: do_other_work() just for that database
No db parameter and an option: do_other_work() for all databases
You do not have to check len(sys.argv) yourself. A properly constructed ArgumentParser will sort that out by itself.
Likewise, you do not need to pass sys.argv[1:] to parse_args(), argparse will figure it out.
default=None and required=False are default values for an optional argument (those starting with '-'), you do not need to supply them.
You do not need to use a lambda to specify the function to call, just pass in the name of the function: it will simplify handling this parameters.
You can add do_work as a default value for '-a': no more TypeError as the content of parsed_args.cmd will alway be a callable.
There is no need in using a mutually exclusive group if you only ever put one option in it: remove it.
You should use if __name__ == '__main__': and put your top-level code under it.
In do_*work you should test database using is None or is not None.




def do_work(database=None):
    if database is not None:
        print 'Doing work for {0}'.format(database)
    else:
        print 'Doing work all database'

def do_other_work(database=None):
    if database is not None:
        print 'Doing other work for {0}'.format(database)
    else:
        print 'Doing other work all database'

def create_parser():
    parser = ArgumentParser(description='Parser')
    parser.add_argument('--db', '-d', dest='database', help='Database name')
    parser.add_argument('-a', dest='cmd', action='store_const',
                        const=do_other_work, default=do_work)
    return parser


if __name__ == '__main__':
    parsed_args = create_parser().parse_args()
    parserd_args.cmd(parsed_args.database)