Skip to content

Argparse: "Default" interacts incorrectly/non-intuitively with action='append' and action='extend' #110131

@rhetzler

Description

@rhetzler

Bug report

Bug description:

The documentation for default claims:

The default keyword argument of add_argument(), whose value defaults to None, specifies what value should be used if the command-line argument is not present
which (implicitly) sets the expectation that the default is not used if the command-line argument is present

in it's defense, the strange behaviour is documented in append but not extend

If the default value is non-empty, the default elements will be present in the parsed value for the option, with any values from the command line appended after those default values

However, this behaviour is non-intuitive. The fact that the values will be prepended to the end-user's input is not obvious, furthermore, the end-user is unable to specify a set of parameters that don't contain undesired default values.

    DEFAULT_SET=['a','b','c','d']
    parser = argparse.ArgumentParser()
    parser.add_argument('--items',nargs='+',action='extend',dest='items',choices=DEFAULT_SET,default=DEFAULT_SET)
    args = parser.parse_args()

    print(args.items)

$ python3 example.py --items a --items b c # expected: items will contain 'a', 'b', and 'c'
['a', 'b', 'c', 'd', 'a', 'b', 'c']

Now it's fair to say that there's a workaround:

    parser.add_argument('--items',nargs='+',action='extend',dest='items',choices=DEFAULT_SET,default=None)
    args = parser.parse_args()
    if args.items == None:
        args.items = DEFAULT_SET 

however, isn't this the pattern that default= aims to eliminate/alleviate in the first place?

If the purpose of DEFAULT is to supply a value in the absense of user input, the fact that it supplies a value even when the user supplies input is an undesired side effect and not really default behaviour.

If the code needs to always be processing a set of values regardless of user input, then that really should be clearly stated in the code/logic, rather than a side effect of the input parsing

    do_something(DEFAULT_SET + args.items) # no ambiguity

hope this makes sense. thank you!

CPython versions tested on:

3.8

Operating systems tested on:

macOS

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.12only security fixes3.13bugs and security fixes3.14bugs and security fixesdocsDocumentation in the Doc dirstdlibStandard Library Python modules in the Lib/ directory

    Projects

    Status

    Doc issues

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions