If there's an ArgumentParser
defined like this:
parser.add_argument("--list", type=str, nargs="+", default=["arg"])
args = parser.parse_args()
the list
type arguments can have their default values overridden by setting the argument to an empty string:
python test.py --list ""
and adding logic to filter list
type args for None
:
for arg, value in args._get_kwargs():
if isinstance(value, list):
setattr(args, arg, list(filter(None, value)))
Is there anyway to do this without accessing the private method of argparse.Namespace
...ideally only changing what's passed from the command-line?
What you want is to create a custom Action class:
#!/usr/bin/env python3
import argparse
class NonEmptyListElementAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string):
values = values or []
# Get the list of values
dest = getattr(namespace, self.dest) or []
# Add to the list only those none empty values
dest.extend(filter(None, values))
# Update the namespace
setattr(namespace, self.dest, dest)
parser = argparse.ArgumentParser()
parser.add_argument("--list", nargs="+", action=NonEmptyListElementAction)
args = parser.parse_args()
print(args)
Sample run:
$ python3 main.py --list one "" two --list "" three --list ""
Namespace(list=['one', 'two', 'three'])
The namespace
argument to __call__
specifies the namespace object
In the action class, self.dest
refers to the name which you can get/set within the namespace. In this case, self.dest
is "list", taken after the --list
part in add_argument
The parser
and option_string
parameters are not use in this example
values
is a list of values from command line. It is ['one', '', 'two']
in the first call, [''', 'three']
in the second call, and ['']
in the last call