Elad Benda
Elad Benda

Reputation: 36656

parser.parse_args boolean parse "False" as True

When I run my python code with -rm False I still see _REMOVE_ADS = True.

How can I fix this?

parser.add_argument(
    "-rm",
    "--remove_ads",
    type=bool,
    required=False,
    default=False,
    help="Should remove disapproved ads. Default: false",
)
# TODO: Fix booleans
args = parser.parse_args()
_REMOVE_ADS = args.remove_ads
print(_REMOVE_ADS)

Upvotes: 1

Views: 294

Answers (1)

wim
wim

Reputation: 362557

This is because they are parsed as strings and any non-empty string is considered True by bool:

>>> bool("False")
True

To fix it, use a different type instead of type=bool, for Python < 3.10 there is a standard lib option which can be used:

from distutils.util import strtobool

You can register this type with a name on a parser instance:

from distutils.util import strtobool

parser = ArgumentParser(...)
parser.register('type', 'boolean', strtobool)
parser.add_argument('-rm', type='boolean')

Alternatively, just make this option into a flag so it doesn't need to accept an argument at all, although note that this does change your CLI usage syntax:

parser.add_argument(
    "-rm", "--remove-ads",
    action="store_true",
    help="Should remove disapproved ads",
)

In Python 3.10 the distutils module has been deprecated. The Migration Advice section of PEP-632 says there is no replacement for the strtobool function and you will need to re-implement the functionality yourself, but that should be easy enough (tweak as necessary):

def strtobool(val): 
    if val.lower().startswith("t"): 
        return True 
    elif val.lower().startswith("f"): 
        return False 
    raise argparse.ArgumentTypeError("invalid boolean value: {!r}".format(val)) 

Upvotes: 2

Related Questions