Search code examples
pythonargparse

argparse: Default value for nargs='*'?


I tried to use this statement :

parser = argparse.ArgumentParser()
parser.add_argument('-m', '--music', nargs='*', default=False, const=True)
args = parser.parse_args()
print(args.music)

But got this error:

`builtins.ValueError: nargs must be '?' to supply const`

what i want to do is :

  • if -m is in args list but whithout any value, args.music will give me True
  • if -m is in args list and have 'N' values, args.music will give me a list of all values
  • if -m is not in args list, args,music will return False

the second and lastOne worked but, when i try to use const i got an error


Solution

  • You could use a custom action:

    import argparse
    class EmptyIsTrue(argparse.Action):
        def __call__(self, parser, namespace, values, option_string=None):
            if len(values) == 0:
                values = True
            setattr(namespace, self.dest, values)
    
    parser = argparse.ArgumentParser()
    parser.add_argument('-m', '--music', nargs='*', default=False, action=EmptyIsTrue)
    print(parser.parse_args([]))
    # Namespace(music=False)
    
    print(parser.parse_args(['-m']))
    # Namespace(music=True)
    
    print(parser.parse_args('-m 1 2'.split()))
    # Namespace(music=['1', '2'])
    

    If you have only one argument to handle this way, then

    arg.music = True if len(arg.music) == 0 else arg.music
    

    is simpler. If you have many such arguments, then defining a custom action could reduce the repetition, and help ensure all those arguments are treated the same way.