This can be done using a special action:
import argparse class OneOrThree(argparse.Action): def __call__(self, parser, namespace, values, option_string=None): if len(values) == 1: setattr(namespace, self.dest, values) setattr(namespace, 'result', decimal_to_dms(*values)) elif len(values) == 3: setattr(namespace, self.dest, values) setattr(namespace, 'result', dms_to_decimal(*values)) else: raise parser.error('Expected 1 or 3 arguments') def dms_to_decimal(deg,minute,sec): assert float(minute) < 60.0, 'Mintue value: %s must be less than 60' % float(minute) assert float(sec) < 60.0, 'Second value: %s must be less than 60' % float(sec) return float(deg)+float(minute)/60.0+float(sec)/(60.0*60.0) def decimal_to_dms(deg): minute = 60.0*(deg-int(deg)) sec = 60.0*(minute-int(minute)) return int(deg),int(minute),sec parser = argparse.ArgumentParser( usage='%(prog)s deg [minute, sec]',) parser.add_argument('dms_args', nargs='+', type=float, action=OneOrThree, metavar='deg [minute, sec]', help='Given one arg, returns dms. Given three args, returns deg') args = parser.parse_args() print(args.result)
Running above leads to the following:
% test.py 12.5 (12, 30, 0.0) % test.py 12 30 0.0 12.5
If the wrong number of arguments is specified, an error occurs:
% test.py 12 30 usage: test.py [-h] dms_args [dms_args ...] test.py: error: Expected 1 or 3 arguments
The help message is as follows:
% test.py -h usage: test.py deg [minute, sec] positional arguments: deg [minute, sec] Given one arg, returns dms. Given three args, returns deg optional arguments: -h, --help show this help message and exit