How do I add an optional flag to my command line args?
eg. so I can write
python myprog.py
or
python myprog.py -w
I tried
parser.add_argument('-w')
But I just get an error message saying
Usage [-w W]
error: argument -w: expected one argument
which I take it means that it wants an argument value for the -w option. What's the way of just accepting a flag?
I'm finding http://docs.python.org/library/argparse.html rather opaque on this question.
-
4If you just want 1 flag to your script, sys.argv would be a whole lot easier. Unless your specifically trying to learn argparse, which is a good because its a handy module to know.chown– chown2011年11月24日 15:08:34 +00:00Commented Nov 24, 2011 at 15:08
-
21Even after I know the answer now I don't see how I could have understood it from the documentation.Andreas Haferburg– Andreas Haferburg2019年07月30日 12:40:35 +00:00Commented Jul 30, 2019 at 12:40
5 Answers 5
As you have it, the argument w is expecting a value after -w on the command line. If you are just looking to flip a switch by setting a variable True or False, have a look here (specifically store_true and store_false)
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-w', action='store_true')
where action='store_true' implies default=False.
Conversely, you could haveaction='store_false', which implies default=True.
2 Comments
w is always False.Adding a quick snippet to have it ready to execute:
Source: myparser.py
import argparse
parser = argparse.ArgumentParser(description="Flip a switch by setting a flag")
parser.add_argument('-w', action='store_true')
args = parser.parse_args()
print args.w
Usage:
python myparser.py -w
>> True
Comments
Your script is right. But by default is of None type. So it considers true of any other value other than None is assigned to args.argument_name variable.
I would suggest you to add a action="store_true". This would make the True/False type of flag. If used its True else False.
import argparse
parser = argparse.ArgumentParser('parser-name')
parser.add_argument("-f","--flag",action="store_true",help="just a flag argument")
usage
$ python3 script.py -f
After parsing when checked with args.f it returns true,
args = parser.parse_args()
print(args.f)
>>>true
Comments
If you are looking for a binary flag, then the argparse actions store_true or store_false provide exactly this. This approach is well explained in the accepted answer by @Jdog.
The official docs are also fairly clear. I would only complete the example with one line, so to make it very clear how the store_true/store_false act:
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', action='store_true')
>>> parser.add_argument('--fov', action='store_true') # this is not in the docs!
>>> parser.add_argument('--bar', action='store_false')
>>> parser.add_argument('--baz', action='store_false')
>>> parser.parse_args('--foo --bar'.split()) # --baz and --fov are missing
Out[4]: Namespace(bar=False, baz=True, foo=True, fov=False) # mind the fov=False
A slightly more powerful approach is to use the count action. You typically have used this type of flag already when setting the verbosity level when running a command.
For example ssh's verbose mode flag -v is a counter:
-v Verbose mode. Causes ssh to print debugging messages about its progress. This is helpful in debugging connection, authentication, and configuration problems. Multiple -v options increase the verbosity. The maximum is 3.
So if you run ssh it's non verbose, ssh -v is slightly verbose and ssh -vvv is maximally verbose.
With argparse in python such a counter flag can be defined as follows:
parser.add_argument('--verbose', '-v', action='count', default=0)
If you want to use it as a boolena (True/False) flag, then you need to cast args.verbose into a boolean. You can either do this explicitly yourself, or rely a conditional statement like if args.verbose: ....
Here is a full working example to illustrate how you can use the counter flag:
With the script test.py:
#!/usr/bin/env python3
# test.py
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--verbose', '-v', action='count', default=0)
args = parser.parse_args()
if args.verbose:
print('verbose')
print(f'verbosity level: {args.verbose}')
else:
print('non-verbose')
You get the following outputs:
python test.py
>> non-verbose
python test.py -v
>> verbose
>> verbosity level: 1
python test.py -vvv
>> verbose
>> verbosity level: 3
1 Comment
Here's a quick way to do it, won't require anything besides sys.. though functionality is limited:
flag = "--flag" in sys.argv[1:]
[1:] is in case if the full file name is --flag
3 Comments
--flag, then it will behave unexpectedly, and what's worse, is that this often ends up being a security flaw down the road, when untrusted data ends up being passed to argv. In the end, this method just shouldn't be done. Real arg parsers are just far more robust...Explore related questions
See similar questions with these tags.