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')