Reputation: 333
The following function and usage examples illustrate exactly what I need with this usage:
test([{True | False}])
:
>>> def test(arg=True):
... if arg:
... print "argument is true"
... else:
... print "argument is false"
...
>>> test()
argument is true
>>> test(True)
argument is true
>>> test(False)
argument is false
>>> test(1)
argument is true
>>> test(0)
argument is false
>>> test("foo")
argument is true
>>> test("")
argument is false
>>>
Now I want exactly the same usage and behaviour but with command-line parsing, i.e. with this usage:
python test [{True | False}]
So I am trying to sort out how to do it with something like this:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-arg",
help="I want the usage to be [{True | False}] (defaults to True)")
arg = parser.parse_args().arg
if arg:
print "argument is true"
else:
print "argument is false"
But I can't figure it out. I tried all sorts of options and combinations of options among which action="store_true"
, default=True
, choices=[True, False]
, type=bool
but nothing works as I would like, e.g.:
$ python test.py -h
usage: test.py [-h] [-arg ARG]
optional arguments:
-h, --help show this help message and exit
-arg ARG I want the usage to be [{True | False}] (defaults to True)
$ python test.py
argument is true
$ python test.py True
usage: test.py [-h] [-arg ARG]
test.py: error: unrecognized arguments: True
etc.
Thanks for any help.
Upvotes: 1
Views: 4306
Reputation: 231355
Find or write a function that parses strings like 'True', 'False'. For example http://www.noah.org/wiki/Python_notes#Parse_Boolean_strings
def ParseBoolean (b):
# ...
if len(b) < 1:
raise ValueError ('Cannot parse empty string into boolean.')
b = b[0].lower()
if b == 't' or b == 'y' or b == '1':
return True
if b == 'f' or b == 'n' or b == '0':
return False
raise ValueError ('Cannot parse string into boolean.')
Think of this as the boolean equivalent of int()
and float()
Then just use it as the argument type
p.add_argument('foo',type=ParseBoolean)
bool()
doesn't work because the only string it interprets as False
is ''
.
Upvotes: 2
Reputation: 333
Thanks to varesa who put me on the way I could find this solution:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("arg",
nargs="?",
default="True",
help="I want the usage to be [{True | False}] (defaults to True)")
arg = parser.parse_args().arg
if arg == "True":
arg = True
elif arg == "False":
arg = False
else:
try:
arg = float(arg)
if arg == 0.:
arg = True
else:
arg = False
except:
if len(arg) > 0:
arg = True
else:
arg = False
if arg:
print "argument is true"
else:
print "argument is false"
However it seems to me quite complicated. Am I dumb (I am new to Python) or could there be a more simple, more straightforward, more elegant way of doing this? A way that would be close to the very straightforward way that a function handles it, as shown in the original posting.
Upvotes: 1
Reputation: 2419
If you give the parameter a name that starts with "-" it will become a flag parameter. As you can see from the "usage" it excepts it to be called test.py -arg True
If you do not want to put -arg
before the argument itself you should name it just arg
, so it will become a positional argument.
Reference: http://docs.python.org/dev/library/argparse.html#name-or-flags
Also it by default will convert the parameters into strings. So if arg:
does not work. The result would be the same as if you called if "foo":
.
If you want to be able to type True
or False
on the command line you will probably want to keep them as strings and use if arg == "True"
. Argparse supports boolean arguments, but as far as I know they only support the form: test.py --arg
results in arg=true, while just test.py
will result in arg=false
Reference: http://docs.python.org/dev/library/argparse.html#type
Upvotes: 1