Parsing boolean values with argparse Parsing boolean values with argparse python python

Parsing boolean values with argparse


I think a more canonical way to do this is via:

command --feature

and

command --no-feature

argparse supports this version nicely:

parser.add_argument('--feature', dest='feature', action='store_true')parser.add_argument('--no-feature', dest='feature', action='store_false')parser.set_defaults(feature=True)

Of course, if you really want the --arg <True|False> version, you could pass ast.literal_eval as the "type", or a user defined function ...

def t_or_f(arg):    ua = str(arg).upper()    if 'TRUE'.startswith(ua):       return True    elif 'FALSE'.startswith(ua):       return False    else:       pass  #error condition maybe?


Yet another solution using the previous suggestions, but with the "correct" parse error from argparse:

def str2bool(v):    if isinstance(v, bool):        return v    if v.lower() in ('yes', 'true', 't', 'y', '1'):        return True    elif v.lower() in ('no', 'false', 'f', 'n', '0'):        return False    else:        raise argparse.ArgumentTypeError('Boolean value expected.')

This is very useful to make switches with default values; for instance

parser.add_argument("--nice", type=str2bool, nargs='?',                        const=True, default=False,                        help="Activate nice mode.")

allows me to use:

script --nicescript --nice <bool>

and still use a default value (specific to the user settings). One (indirectly related) downside with that approach is that the 'nargs' might catch a positional argument -- see this related question and this argparse bug report.


If you want to allow --feature and --no-feature at the same time (last one wins)

This allows users to make a shell alias with --feature, and overriding it with --no-feature.

Python 3.9 and above

parser.add_argument('--feature', default=True, action=argparse.BooleanOptionalAction)

Python 3.8 and below

I recommend mgilson's answer:

parser.add_argument('--feature', dest='feature', action='store_true')parser.add_argument('--no-feature', dest='feature', action='store_false')parser.set_defaults(feature=True)

If you DON'T want to allow --feature and --no-feature at the same time

You can use a mutually exclusive group:

feature_parser = parser.add_mutually_exclusive_group(required=False)feature_parser.add_argument('--feature', dest='feature', action='store_true')feature_parser.add_argument('--no-feature', dest='feature', action='store_false')parser.set_defaults(feature=True)

You can use this helper if you are going to set many of them:

def add_bool_arg(parser, name, default=False):    group = parser.add_mutually_exclusive_group(required=False)    group.add_argument('--' + name, dest=name, action='store_true')    group.add_argument('--no-' + name, dest=name, action='store_false')    parser.set_defaults(**{name:default})add_bool_arg(parser, 'useful-feature')add_bool_arg(parser, 'even-more-useful-feature')