Mutually exclusive option groups in python Click

I ran into this same use case recently; this is what I came up with. For each option, you can give a list of conflicting options.

from click import command, option, Option, UsageError

class MutuallyExclusiveOption(Option):
    def __init__(self, *args, **kwargs):
        self.mutually_exclusive = set(kwargs.pop('mutually_exclusive', []))
        help = kwargs.get('help', '')
        if self.mutually_exclusive:
            ex_str=", ".join(self.mutually_exclusive)
            kwargs['help'] = help + (
                ' NOTE: This argument is mutually exclusive with '
                ' arguments: [' + ex_str + '].'
        super(MutuallyExclusiveOption, self).__init__(*args, **kwargs)

    def handle_parse_result(self, ctx, opts, args):
        if self.mutually_exclusive.intersection(opts) and in opts:
            raise UsageError(
                "Illegal usage: `{}` is mutually exclusive with "
                "arguments `{}`.".format(
                    ', '.join(self.mutually_exclusive)

        return super(MutuallyExclusiveOption, self).handle_parse_result(

Then use the regular option decorator but pass the cls argument:

@command(help="Run the command.")
@option('--jar-file', cls=MutuallyExclusiveOption,
        help="The jar file the topology lives in.",
        help="The jar file the topology lives in.",
def cli(jar_file, other_arg):
    print "Running cli."
    print "jar-file: {}".format(jar_file)
    print "other-arg: {}".format(other_arg)

if __name__ == '__main__':

Here’s a gist
that includes the code above and shows the output from running it.

If that won’t work for you, there’s also a few (closed) issues mentioning this on the click github page with a couple of ideas that you may be able to use.

Leave a Comment