Joel Daroussin
Joel Daroussin

Reputation: 333

how to parse a boolean argument in a script?

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

Answers (3)

hpaulj
hpaulj

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

Joel Daroussin
Joel Daroussin

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

varesa
varesa

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

Related Questions