I have a question regarding python\'s argparse: Is it possible to have a optional argument, which does not require positional arguments?
Example:
parser.
nargs='?'
for your positional argumentscheck manually in your code that both latitude and longitude have been set when you're not in list-methods mode
parser = argparse.ArgumentParser()
parser.add_argument('lat', help="latitude",default=None, nargs='?')
parser.add_argument('lon', help="longitude",default=None, nargs='?')
parser.add_argument('--method', help="calculation method (default: add)", default="add")
parser.add_argument('--list-methods', help="list available methods", action="store_true")
args = vars(parser.parse_args())
if not args['list_methods'] and (args['lat'] == None or args['lon'] == None):
print '%s: error: too few arguments' % sys.argv[0]
exit(0)
if args['list_methods']:
print 'list methods here'
else :
print 'normal script execution'
which gives :
$ test.py --list-methods
list methods here$ test.py 4
test.py: error: too few argumentstest.py 4 5
normal script execution
As of Python 3.3, parse_args
checks its set of seen_actions
against the set of actions that are required, and issues a the following arguments are required...
error as needed. Previously it checked its list of remaining positionals
and raised the too few arguments
error message.
So for newer versions, this snippet should do what you want:
parser = argparse.ArgumentParser()
lat=parser.add_argument('lat', help="latitude")
lon=parser.add_argument('lon', help="longitude")
parser.add_argument('--method', help="calculation method (default: add)", default="add")
class MyAction(argparse._StoreTrueAction):
def __call__(self, parser, namespace, values, option_string=None):
setattr(namespace, self.dest, self.const)
lat.required = False
lon.required = False
parser.add_argument('--list-methods', help="list available methods", action=MyAction)
Normally lat
and lon
are required positionals, but if the --list...
action is taken, those actions are no longer required, and no error message is raised if they are missing.
Another way to customize argparse is to use several parsers. In this case you could use one parser to check for the --list-methods
option, and based on what it gets, call another that looks for the positionals.
parser1 = argparse.ArgumentParser(add_help=False)
parser1.add_argument('--list-methods', help="list available methods", action='store_true')
parser2 = argparse.ArgumentParser()
parser2.add_argument('lat', help="latitude")
parser2.add_argument('lon', help="longitude")
parser2.add_argument('--method', help="calculation method (default: add)", default="add")
parser2.add_argument('--list-methods', help="list available methods", action='store_true')
def foo(argv):
args,rest = parser1.parse_known_args(argv)
if not args.list_methods:
args = parser2.parse_args(argv)
return args
parser2
responds to the help command. parse_known_args
parses what it can, and returns the rest in a list. parser2
could also have been write to take rest, args
as arguments.
You get error: to few arguments
because lat
and lon
arguments are required.
In [10]: parser.parse_args('--list-methods'.split())
ipython: error: too few arguments
but
In [11]: parser.parse_args('--list-methods 10 20'.split())
Out[11]: Namespace(lat='10', list_methods=True, lon='20', method='add')
You should make lat
and lon
arguments optional.