Explain Codes LogoExplain Codes Logo

Parsing boolean values with argparse

python
argparse
boolean-arguments
command-line
Anton ShumikhinbyAnton Shumikhin·Aug 7, 2024
TLDR

The argparse module is your best friend for parsing command-line boolean flags. You'll primarily use action='store_true' and action='store_false' for binary choices. Consider making a dedicated function, str2bool, for those tricky string representations of booleans that we all know and love.

Example:

import argparse # This function is 50% lie detector, 50% truth serum def str2bool(v): """ Here to elegantly slice through strings like 'yes', 'true', 't' and give you the truth. If fed a lie (or invalid inputs), will make its displeasure known (Raises ArgumentTypeError) """ 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.') parser = argparse.ArgumentParser() # "There is no spoon" will not pass this test! parser.add_argument('--flag', type=str2bool, nargs='?', const=True, default=False, help='Boolean arg') args = parser.parse_args() print(f'Flag is {"on" if args.flag else "off"}') #Matrix reference, anyone?

Run this with --flag=yes or don't — we handle False too; --flag with no value flips it to True. Just like a light switch, except way cooler.

Boolean flags: the Argparse way

In the modernizing Python world (3.9+), argparse offers BooleanOptionalAction for built-in support for boolean flags. Cutting out the middleman is always welcome, isn't it?

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

This enables --feature or --no-feature options without needing an extra input value. Partly magic, mainly convenience.

Earlier Python versions allow argparse to shine with its action='store_true' or action='store_false' parameters. No black or white here; just pick the one you prefer.

Choose your side: enabling and disabling features

Argparse allows you to specify boolean arguments in a user-friendly way. Create flags like --enable-feature and --disable-feature to increase understanding and avoid ambiguity.

Default to consistency: using set_defaults()

As a gatekeeper, it’s crucial for argparse to hold the fort against all odds. By using parser.set_defaults(), you can wield the power to set default values for your arguments:

parser.set_defaults(feature=True)

Wield this power wisely, and argparse will stand by you like a true knight.

Returns: Handling various types in str2bool

The str2bool function can sometimes surprise you by returning a boolean from an existing boolean input. It’s almost like an echo, but much less annoying:

def str2bool(v): """ If v could vote, it would vote for its own truth. But since it can’t, str2bool is here to do it justice. """ if isinstance(v, bool): return v

Pro tips and hacks for argparse usage

Careful with nargs='?'

Using nargs='?' can be a bit like working with a sword swallower. It's a cool trick, but if you don't know what you're doing, things can go wrong fast. It's totally manageable, though — just requires a meaningful relationship with positional arguments.

Avoid type=bool

Type=bool might sound like solution to all boolean-related problems, but it comes with an unexpected twist. bool("False") in Python gives True (surprise!). So avoid using it, unless you want to enter Python's version of the Twilight Zone.

Craft a helper function for boolean arguments

Simplify your life with a helper function, add_bool_arg, which makes argparse understand and manage boolean arguments in an elegant manner:

def add_bool_arg(parser, name, default=False, help=None): ''' Because even argparse needs a little help sometimes. This function is argparse's assistance dog for fetching booleans. ''' group = parser.add_mutually_exclusive_group() group.add_argument(f'--{name}', dest=name, action='store_true', default=default, help=help) group.add_argument(f'--no-{name}', dest=name, action='store_false', default=default)

Ensure error-handling is robust

Can't ignore the importance of good error handling, can we? Don't let your argparse castle crumble under the weight of invalid arguments. A well-placed argparse.ArgumentTypeError throws the error right back⁠, like a catapult.

Aim for efficient parsing

Start your script with robust boolean parsing for efficiency and clear command-line interaction. Place parsers at the top, and watch it roll down smoothly. You'll thank yourself for it.

Define clear triggers for boolean states

Establish clear strings (like 'true', 'false') as triggers for boolean state switches. Display them aptly in your str2bool or similar function for easy reference.