zzzbbx
zzzbbx

Reputation: 10161

Reading default arguments with argparse

When using something like this with argparse:

parser.add_argument("-option1", type=int, nargs=1, default=1, choices=xrange(1, 10), help="option 1 message")

If the argument is not passed, args.option1 is an integer. If an argument is passed, args.option is a list.

Which means I have to use either args.option1 or args.option1[0]. Is it possible to avoid this?

Upvotes: 2

Views: 597

Answers (2)

hlt
hlt

Reputation: 6317

You get a list because you set nargs=1 in the arguments to add_argument. This is also outlined in the docs:

Note that nargs=1 produces a list of one item. This is different from the default, in which the item is produced by itself.

If you remove nargs=1, it should produce the item on its own as desired (from the argument if given, otherwise from default). Should you want to make the number optional (i.e. also allow -option1 without argument), use nargs='?' and set const as the default value for that case.

Upvotes: 1

Martijn Pieters
Martijn Pieters

Reputation: 1125398

If you set nargs to an integer, the argument will always be a list when specified. You could use '?' instead to have it set to a single value or the default:

parser.add_argument(
    "-option1", type=int, nargs='?', default=1, 
    choices=xrange(1, 10), help="option 1 message")

From the nargs documentation:

  • N (an integer). N arguments from the command line will be gathered together into a list.

[...]

  • '?'. One argument will be consumed from the command line if possible, and produced as a single item. If no command-line argument is present, the value from default will be produced.

Emphasis mine. You probably want to set const as well though, in case someone uses just -option1 on the command line with no value following it; without const the value is then set to None. Just set it to the same value as the default:

parser.add_argument(
    "-option1", type=int, nargs='?', default=1, const=1,
    choices=xrange(1, 10), help="option 1 message")

Another option is to not set nargs:

parser.add_argument(
    "-option1", type=int, default=1, 
    choices=xrange(1, 10), help="option 1 message")

This usually means almost the same as nargs='?':

If the nargs keyword argument is not provided, the number of arguments consumed is determined by the action. Generally this means a single command-line argument will be consumed and a single item (not a list) will be produced.

with the difference being that an empty -option1 argument on the command line is not permitted; no const needs to be set.

Demo:

>>> from argparse import ArgumentParser
>>> parser = ArgumentParser()
>>> parser.add_argument(
...     "-option1", type=int, nargs='?', default=1, const=1,
...     choices=xrange(1, 10), help="option 1 message")
_StoreAction(option_strings=['-option1'], dest='option1', nargs='?', const=1, default=1, type=<type 'int'>, choices=xrange(1, 10), help='option 1 message', metavar=None)
>>> parser.parse_args(['-option1', '4'])  # option with argument
Namespace(option1=4)
>>> parser.parse_args(['-option1'])       # option with *no* argument
Namespace(option1=1)
>>> parser.parse_args([])                 # option not specified
Namespace(option1=1)
>>> parser = ArgumentParser()
>>> parser.add_argument(
...     "-option1", type=int, default=1, 
...     choices=xrange(1, 10), help="option 1 message")
_StoreAction(option_strings=['-option1'], dest='option1', nargs=None, const=None, default=1, type=<type 'int'>, choices=xrange(1, 10), help='option 1 message', metavar=None)
>>> parser.parse_args(['-option1', '4'])  # option with argument
Namespace(option1=4)
>>> parser.parse_args([])                 # option not specified
Namespace(option1=1)
>>> parser.parse_args(['-option1'])       # option with *no* argument
usage: [-h] [-option1 {1,2,3,4,5,6,7,8,9}]
: error: argument -option1: expected one argument

Upvotes: 2

Related Questions