argparse: Default value for nargs='*'?
Question:
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
Answers:
The following hack after the argparse
section solves your problem:
import argparse
# Same as your code above
parser = argparse.ArgumentParser()
parser.add_argument('-m', '--music', nargs='*', default=False)
args = parser.parse_args()
# Modifies args.music: [] -> True
args.music = True if args.music==[] else args.music
print(args.music)
Tested in the command line, it gives:
$ python /tmp/blah.py -m
True
$ python /tmp/blah.py -m 1 -m 2
['2']
$ python /tmp/blah.py -m 1 2 3
['1', '2', '3']
$ python /tmp/blah.py
False
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.
What about :
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-m', '--music', nargs='*', default=False)
args = parser.parse_args()
if vars(args).get('music', False) is not False:
if not args.music:
args.music = True
print args.music
Output:
tmp:/>python arg.py
False
tmp:/>python arg.py -m
True
tmp:/>python arg.py -m 1 2 3
['1', '2', '3']
tmp:/>
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
The following hack after the argparse
section solves your problem:
import argparse
# Same as your code above
parser = argparse.ArgumentParser()
parser.add_argument('-m', '--music', nargs='*', default=False)
args = parser.parse_args()
# Modifies args.music: [] -> True
args.music = True if args.music==[] else args.music
print(args.music)
Tested in the command line, it gives:
$ python /tmp/blah.py -m
True
$ python /tmp/blah.py -m 1 -m 2
['2']
$ python /tmp/blah.py -m 1 2 3
['1', '2', '3']
$ python /tmp/blah.py
False
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.
What about :
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-m', '--music', nargs='*', default=False)
args = parser.parse_args()
if vars(args).get('music', False) is not False:
if not args.music:
args.music = True
print args.music
Output:
tmp:/>python arg.py
False
tmp:/>python arg.py -m
True
tmp:/>python arg.py -m 1 2 3
['1', '2', '3']
tmp:/>