Argparse: add_argument with action=append appends to default

Peter Otten __peter__ at web.de
Thu Sep 16 03:26:32 EDT 2010


John O'Hagan wrote:

> I find this surprising:
> 
>>>> import argparse
>>>> parser = argparse.ArgumentParser()
>>>> parser.add_argument('--test', action='append', default=['default'])
> [...]
>>>> parser.parse_args(['--test', 'arg'])
> Namespace(test=['default', 'arg'])
> 
> As an argument is provided, I didn't expect to see the default in there as
> well. From the argparse docs: "the default value is used when the option
> string was not present at the command line". While it doesn't say "_only_
> when...", that's what I would have expected.
> 
> Is there a reason for this behaviour? Is there a way to do what I want, to
> get a list of appended options _or_ a default list (apart from setting
> defaults outside the parser, a good way to lose track of things)?

You could either tweak the default value or the action:

$ cat append.py
import argparse

class DefaultList(list):
    def __copy__(self):
        return []

if __name__ == "__main__":
    p = argparse.ArgumentParser()
    p.add_argument("-t", "--test", action="append", 
default=DefaultList(["default"]))

    print p.parse_args()
$ python append.py -t one -t two
Namespace(test=['one', 'two'])
$ python append.py -t one
Namespace(test=['one'])
$ python append.py
Namespace(test=['default'])


$ cat append1.py
import argparse

class DefaultAppend(argparse._AppendAction):
    def __call__(self, parser, namespace, values, option_string=None):
        items = argparse._copy.copy(argparse._ensure_value(namespace, 
self.dest, []))
        try:
            self._not_first
        except AttributeError:
            self._not_first = True
            del items[:]
        items.append(values)
        setattr(namespace, self.dest, items)

if __name__ == "__main__":
    p = argparse.ArgumentParser()
    p.add_argument("-t", "--test", action=DefaultAppend, 
default=["default"])
    print p.parse_args()
$ python append1.py -t one -t two
Namespace(test=['one', 'two'])
$ python append1.py -t one
Namespace(test=['one'])
$ python append1.py
Namespace(test=['default'])

Peter



More information about the Python-list mailing list